Compare commits

...

20 Commits

Author SHA1 Message Date
Dustin 131c872d32 Merge remote-tracking branch 'refs/remotes/origin/master' 2018-07-29 10:02:28 -05:00
Dustin 9bf2a911c6 roles/dch-proxy: Switch default backend to web0.p.b
The public-facing websites are now hosted by *web0.pyrocufflink.blue*
and *myala.pyrocufflink.jazz* has been decommissioned.
2018-07-29 09:41:10 -05:00
Dustin 67fc5c8c05 hosts: Add web0.p.b
*web0.pyrocufflink.blue* hosts the public-facing websites
2018-07-29 09:39:02 -05:00
Dustin 2d8418c7a7 websites: PB to deploy public-facing websites 2018-07-29 09:37:47 -05:00
Dustin 33ee3bf08d websites: Add role for darkchestofwonders.us
The *websites/darkchestofwonders.us* role prepares a machine to host
http://darkchestofwonders.us/. The website itself is published via rsync
by Jenkins.
2018-07-29 09:34:41 -05:00
Dustin 1f16b4c3e4 websites: Add role for nratonpass.com
The *websites/nratonpass.com* role prepares a machine to host
http://nratonpass.com/. The website itself is published via rsync by
Jenkins.
2018-07-29 09:34:21 -05:00
Dustin ae5d8bee56 websites: Add role for ebonfire.com
The *websites/ebonfire.com* role prepares a machine to host
http://ebonfire.com/. The website itself is published via rsync by
Jenkins.
2018-07-29 09:33:31 -05:00
Dustin 3d46e6b411 websites: Add role for dustin.hatch.name
The *websites/dustin.hatch.name* role configures a server to host
http://dustin.hatch.name/. The role only applies basic configuration;
the actual website application is published by Jenkins.
2018-07-29 09:32:19 -05:00
Dustin 4a5d319a17 roles/certbot: Reload Apache before cert requests
The Apache service needs to be reloaded after the *certbot* role
configures it to serve the `/.well-known/acme-challenge` path, so that
the changes can take effect before the `certbot` command is run to
request the certificate(s).
2018-07-29 09:28:12 -05:00
Dustin 9f5f692b6a roles/apache: Do not start Apache
If another role that depends on the *apache* role accidentally creates
an invalid configuration, it will be impossible to correct it by
subsequent invocations of its playbook. This is because the *apache*
role always tries to start the service, which will fail if the
configuration is invalid, thus aborting the playbook. With this early
abort, there is no way for later tasks to correct the error.

Playbooks that include the *apache* role should have a task that is
executed after all the roles have been applied to ensure the service is
running.
2018-07-29 09:25:54 -05:00
Dustin e8f9f48bfd roles/winbind: Actually perform domain join 2018-07-26 16:54:03 -05:00
Dustin 11dc40bc76 hosts: Add vmhost{0,1}.p.b 2018-07-23 17:35:10 -05:00
Dustin a8dd2e9ec3 vmhost: PB to set up VM hosts 2018-07-23 17:35:10 -05:00
Dustin f8ae016042 roles/dch-storage-net: Set up/mount shared storage
The *dch-storage-net* role configures a machine to connect the storage
network and mount shared folders from the storage appliance.

The `wait-global-address.sh` script and corresponding
*wait-global-address@.service* systemd unit template are necessary to
ensure that the storage network is actually available before attempting
to mount the shared volumes. This is particularly important at boot,
since `dhcpcd` does not implement any kind of signaling that can be used
by *network-online.target*, so the network is considered "online" as
soon as the `dhcpcd` process has started. This typically results in
"network unreachable" errors.
2018-07-23 17:35:10 -05:00
Dustin abd05f8443 roles/vmhost: Configure libvirtd+QEMU
The *vmhost* role installs and configures the libvirt daemon to host
QEMU/KVM virtual machines.
2018-07-23 17:35:10 -05:00
Dustin 82e8f7f9e7 net-ifaces: PB to apply net-ifaces role 2018-07-23 17:35:10 -05:00
Dustin 704850caa9 roles/net-ifaces: Configure virtual net interfaces
The *net-ifaces* role manages a script that creates virtual network
interfaces, such as bridge, bond, and VLAN, that `dhcpcd`/`dhclient`
alone cannot. This provides a lightweight alternative to
*systemd-networkd* and *NetworkMangager*.
2018-07-23 17:35:10 -05:00
Dustin 44a82688e4 roles/dhcpcd: Always send FQDN
Though the default for the `fqdn` value is listed as `both` in
*dhcpcd.conf(5)*, the current behavior of `dhcpcd` suggests that it may
actually be `none`. Without explicitly setting `fqdn both`, the value of
the kernel node name is sent as-is in the *hostname* option (12). If the
node name is set to the FQDN, then dynamic DNS gets broken, since the
DHCP server always appends its domain name to the provided hostname.
Setting `fqdn both` causes `dhcpcd` to send the FQDN in the *FQDN*
option (81), which the DHCP server interprets correctly.
2018-07-23 17:35:10 -05:00
Dustin 1302cd8825 roles/dhcpcd: Use a list for allow/deny interfaces
Using a list to specify the values for the `allowinterfaces` and
`denyinterfaces` parameters in `dhcpcd.conf` makes the configuration
policy cleaner and more type-safe.
2018-07-23 17:35:10 -05:00
Dustin 620fcc79b8 dch-network: Use dc0.p.b for NTP on test network 2018-07-23 17:35:10 -05:00
45 changed files with 1272 additions and 11 deletions

View File

@ -47,7 +47,7 @@ dch_networks:
- 172.30.0.4
sla_id: 101
ntp_servers:
- tyrande.pyrocufflink.jazz
- dc0.pyrocufflink.blue
guest:
description: Guest Wi-Fi

13
group_vars/vm-hosts.yml Normal file
View File

@ -0,0 +1,13 @@
libvirt_networks:
- name: prod
type: bridge
bridge_iface: br0
- name: test
type: bridge
bridge_iface: br1
storage_host: storage0.pyrocufflink.blue
mount_shared_volumes:
- mountpoint: /var/lib/libvirt/images
host: '[{{ lookup("dig", storage_host, "qtype=AAAA") }}]'
share: /volume1/VirtualMachines
opts: vers=4,intr

View File

@ -0,0 +1,12 @@
dhcpcd_nodev: true
dhcpcd_allow_interfaces:
- enp5s0
- bond1
dhcpcd_interfaces:
- name: bond1
config:
- noipv4
- static ip6_address=fd68:c2d2:500e:3ea3:3c35:bbaf:f9a3:ad9a/64
storage_iface: bond1
samba_interfaces:
- enp5s0

View File

@ -0,0 +1,12 @@
dhcpcd_nodev: true
dhcpcd_allow_interfaces:
- enp5s0
- bond1
dhcpcd_interfaces:
- name: bond1
config:
- noipv4
- static ip6_address=fd68:c2d2:500e:3ea3:8d5f:c3b0:a73c:55d6/64
storage_iface: bond1
samba_interfaces:
- enp5s0

12
hosts
View File

@ -6,6 +6,7 @@ cm0.pyrocufflink.blue
[certbot]
git0.pyrocufflink.blue
web0.pyrocufflink.blue
[dch-gw]
gw0 ansible_host=172.31.0.1
@ -15,6 +16,7 @@ rprx0.pyrocufflink.blue
[dhcpcd:children]
dch-gw
vm-hosts
[dhcpd:children]
dch-gw
@ -34,6 +36,9 @@ dc0.pyrocufflink.blue
[postgresql:children]
zabbix-server
[public-web]
web0.pyrocufflink.blue
[pyrocufflink]
cm0.pyrocufflink.blue
dc0.pyrocufflink.blue
@ -43,6 +48,9 @@ git0.pyrocufflink.blue
jenkins0.pyrocufflink.blue
rprx0.pyrocufflink.blue
smtp0.pyrocufflink.blue
vmhost0.pyrocufflink.blue
vmhost1.pyrocufflink.blue
web0.pyrocufflink.blue
zbx0.pyrocufflink.blue
[pyrocufflink-dns]
@ -70,3 +78,7 @@ zbx0.pyrocufflink.blue
[zabbix:children]
dch-gw
pyrocufflink
[vm-hosts]
vmhost0.pyrocufflink.blue
vmhost1.pyrocufflink.blue

3
net-ifaces.yml Normal file
View File

@ -0,0 +1,3 @@
- hosts: all
roles:
- net-ifaces

View File

@ -3,3 +3,4 @@
*.key
*.pem
*.keytab
*.cnf

View File

@ -87,12 +87,6 @@
with_items: '{{ web_ports }}'
notify: save firewalld configuration
- meta: flush_handlers
- name: ensure httpd service is running
service:
name=httpd
state=started
- name: ensure old apache logs are rotated
template:
src=httpd.logrotate.j2

View File

@ -58,6 +58,7 @@
dest=/etc/httpd/conf.d/certbot.conf
mode=0644
notify: reload httpd
- meta: flush_handlers
- name: ensure letsencrypt account data are installed
become: true

View File

@ -32,3 +32,10 @@
dest=/etc/haproxy/70-backend-openvpn.cfg
mode=0644
notify: reload haproxy
- name: ensure websites haproxy backend is configured
template:
src=backend-websites.haproxy.cfg.j2
dest=/etc/haproxy/70-backend-websites.cfg
mode=0644
notify: reload haproxy

View File

@ -0,0 +1,7 @@
backend web
server web0 web0.pyrocufflink.blue:80 check
backend web-tls
mode tcp
server web web0.pyrocufflink.blue:443 check

View File

@ -5,7 +5,7 @@ frontend main
use_backend gitea if { hdr(host) -i git.pyrocufflink.net }
use_backend jenkins if { hdr(host) -i jenkins.pyrocufflink.blue }
use_backend jenkins if { hdr(host) -i jenkins.pyrocufflink.net }
default_backend myala
default_backend web
frontend main-tls
@ -20,5 +20,5 @@ frontend main-tls
use_backend gitea-tls if { req_ssl_sni -i git.pyrocufflink.net }
use_backend jenkins-tls if { req_ssl_sni -i jenkins.pyrocufflink.blue }
use_backend jenkins-tls if { req_ssl_sni -i jenkins.pyrocufflink.net }
use_backend myala-tls if { req_ssl_sni -i darkchestofwonders.us }
use_backend web-tls if { req_ssl_sni -i darkchestofwonders.us }
default_backend openvpn

View File

@ -0,0 +1,14 @@
[Unit]
Description=Wait for global address on %I
Requires=sys-subsystem-net-devices-%i.device
After=network-pre.target
Before=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/libexec/wait-global-address.sh %I
[Install]
WantedBy=network-online.target

View File

@ -0,0 +1,6 @@
#!/bin/sh
until ip -o address show dev "$1" | grep -q global; do
printf 'Waiting for global address on %s\n' "$1"
sleep 1;
done

View File

@ -0,0 +1,2 @@
- name: reload systemd
command: systemctl daemon-reload

View File

@ -0,0 +1,29 @@
- name: ensure wait-global-address script is installed
copy:
src=wait-global-address.sh
dest=/usr/local/libexec/wait-global-address.sh
mode=0755
- name: ensure wait-global-address unit is installed
copy:
src=wait-global-address.service
dest=/etc/systemd/system/wait-global-address@.service
mode=0644
notify: reload systemd
- name: ensure wait-global-address service starts at boot
service:
name=wait-global-address@{{ storage_iface }}.service
enabled=yes
- name: ensure wait-global-address service is running
service:
name=wait-global-address@{{ storage_iface }}.service
state=started
- name: ensure storage volumes are mounted
mount:
path={{ item.mountpoint }}
src={{ item.host }}:{{ item.share }}
fstype={{ item.fstype|d('nfs') }}
opts={{ item.opts|d(omit) }}
state=mounted
with_items: '{{ mount_shared_volumes }}'

View File

@ -14,11 +14,11 @@ controlgroup {{ dhcpcd_controlgroup }}
{% endif %}
{% if dhcpcd_allow_interfaces is defined %}
allowinterfaces {{ dhcpcd_allow_interfaces }}
allowinterfaces {{ dhcpcd_allow_interfaces|join(' ')}}
{% endif %}
{% if dhcpcd_deny_interfaces is defined %}
denyinterfaces {{ dhcpcd_deny_interfaces }}
denyinterfaces {{ dhcpcd_deny_interfaces|join(' ') }}
{% endif %}
# Inform the DHCP server of our hostname for DDNS.
@ -28,6 +28,9 @@ hostname
#hostname
{% endif %}
# Always send FQDN
fqdn both
# Use the hardware address of the interface for the Client ID.
{% if dhcpcd_use_clientid|bool %}
clientid

View File

@ -0,0 +1,11 @@
[Unit]
Description=Create virtual network interfaces
Before=network.target network-online.target dhcpcd.service
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/net-ifaces.sh
RemainAfterExit=true
[Install]
WantedBy=network.target

View File

@ -0,0 +1,51 @@
#!/bin/sh
set -e
add_slave() {
local master=$1
local slave=$2
ip link set ${slave} down
echo +${slave} > /sys/class/net/${master}/bonding/slaves
ip link set ${slave} up
}
make_bond() {
local bond=$1
local mode=${2:-802.3ad}
if [ ! -d /sys/module/bonding ]; then
modprobe bonding
fi
echo +${bond} > /sys/class/net/bonding_masters
echo ${mode} > /sys/class/net/${bond}/bonding/mode
echo 100 > /sys/class/net/${bond}/bonding/miimon
}
# VM Network
make_bond bond0
add_slave bond0 enp10s0f0
add_slave bond0 enp10s0f1
ip link add link bond0 name vlan30 type vlan id 30
ip link add link bond0 name vlan101 type vlan id 101
ip link set bond0 up
ip link add br0 type bridge
ip link set vlan30 master br0
ip link set br0 up
ip link add br1 type bridge
ip link set vlan101 master br1
ip link set br1 up
# Storage Network
make_bond bond1
add_slave bond1 enp8s0f0
add_slave bond1 enp8s0f1
ip link set bond1 mtu 9000

View File

@ -0,0 +1,52 @@
#!/bin/sh
set -e
add_slave() {
local master=$1
local slave=$2
ip link set ${slave} down
echo +${slave} > /sys/class/net/${master}/bonding/slaves
ip link set ${slave} up
}
make_bond() {
local bond=$1
local mode=${2:-802.3ad}
if [ ! -d /sys/module/bonding ]; then
modprobe bonding
fi
echo +${bond} > /sys/class/net/bonding_masters
echo ${mode} > /sys/class/net/${bond}/bonding/mode
echo 100 > /sys/class/net/${bond}/bonding/miimon
}
# VM Network
make_bond bond0
#add_slave bond0 enp10s0f0
#add_slave bond0 enp10s0f1
add_slave bond0 enp10s0
ip link add link bond0 name vlan30 type vlan id 30
ip link add link bond0 name vlan101 type vlan id 101
ip link set bond0 up
ip link add br0 type bridge
ip link set vlan30 master br0
ip link set br0 up
ip link add br1 type bridge
ip link set vlan101 master br1
ip link set br1 up
# Storage Network
make_bond bond1
add_slave bond1 enp8s0f0
add_slave bond1 enp8s0f1
ip link set bond1 mtu 9000

View File

@ -0,0 +1,2 @@
- name: reload systemd
command: systemctl daemon-reload

View File

@ -0,0 +1,17 @@
- name: ensure net-ifaces script is installed
copy:
src={{ inventory_hostname }}.sh
dest=/usr/local/libexec/net-ifaces.sh
mode=0755
- name: ensure net-ifaces systemd unit is installed
copy:
src=net-ifaces.service
dest=/etc/systemd/system/net-ifaces.service
mode=0644
notify: reload systemd
- name: ensure net-ifaces service starts at boot
service:
name=net-ifaces
enabled=yes

View File

@ -0,0 +1,63 @@
- name: ensure required packages are installed
package:
name={{ vmhost_required_packages|join(',') }}
state=present
tags:
- install
- name: ensure libvirtd is configured
template:
src=libvirtd.conf.j2
dest=/etc/libvirt/libvirtd.conf
mode=0644
- name: ensure libvirt can use nfs
seboolean:
name=virt_use_nfs
state=yes
persistent=yes
- name: ensure libvirt runtime configuration directories exists
file:
path=/var/lib/libvirt/config/{{ item }}
mode=0700
state=directory
with_items:
- qemu
- storage
- name: ensure libvirt runtime directory bind mounts are set
mount:
path: /etc/libvirt/{{ item }}
src: /var/lib/libvirt/config/{{ item }}
fstype: none
opts: bind
state: mounted
with_items:
- qemu
- storage
- name: ensure libvirtd starts at boot
service:
name=libvirtd
enabled=yes
- name: ensure libvirtd is running
service:
name=libvirtd
state=started
- name: ensure libvirt networks are defined
virt_net:
command: define
name: '{{ item.name }}'
xml: '{{ lookup("template", "net-" + item.type + ".xml.j2") }}'
with_items: '{{ libvirt_networks }}'
- name: ensure libvirt networks are active
virt_net:
name: '{{ item.name }}'
state: active
with_items: '{{ libvirt_networks }}'
- name: ensure libvirt networks start at boot
virt_net:
name: '{{ item.name }}'
autostart: true
with_items: '{{ libvirt_networks }}'

View File

@ -0,0 +1,482 @@
# Master libvirt daemon configuration file
#
# For further information consult https://libvirt.org/format.html
#
# NOTE: the tests/daemon-conf regression test script requires
# that each "PARAMETER = VALUE" line in this file have the parameter
# name just after a leading "#".
#################################################################
#
# Network connectivity controls
#
# Flag listening for secure TLS connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# It is necessary to setup a CA and issue server certificates before
# using this capability.
#
# This is enabled by default, uncomment this to disable it
#listen_tls = 0
# Listen for unencrypted TCP connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# Using the TCP socket requires SASL authentication by default. Only
# SASL mechanisms which support data encryption are allowed. This is
# DIGEST_MD5 and GSSAPI (Kerberos5)
#
# This is disabled by default, uncomment this to enable it.
#listen_tcp = 1
# Override the port for accepting secure TLS connections
# This can be a port number, or service name
#
#tls_port = "16514"
# Override the port for accepting insecure TCP connections
# This can be a port number, or service name
#
#tcp_port = "16509"
# Override the default configuration which binds to all network
# interfaces. This can be a numeric IPv4/6 address, or hostname
#
# If the libvirtd service is started in parallel with network
# startup (e.g. with systemd), binding to addresses other than
# the wildcards (0.0.0.0/::) might not be available yet.
#
#listen_addr = "192.168.0.1"
# Flag toggling mDNS advertizement of the libvirt service.
#
# Alternatively can disable for all services on a host by
# stopping the Avahi daemon
#
# This is disabled by default, uncomment this to enable it
#mdns_adv = 1
# Override the default mDNS advertizement name. This must be
# unique on the immediate broadcast network.
#
# The default is "Virtualization Host HOSTNAME", where HOSTNAME
# is substituted for the short hostname of the machine (without domain)
#
#mdns_name = "Virtualization Host Joe Demo"
#################################################################
#
# UNIX socket access controls
#
# Set the UNIX domain socket group ownership. This can be used to
# allow a 'trusted' set of users access to management capabilities
# without becoming root.
#
# This is restricted to 'root' by default.
unix_sock_group = "libvirt"
# Set the UNIX socket permissions for the R/O socket. This is used
# for monitoring VM status only
#
# Default allows any user. If setting group ownership, you may want to
# restrict this too.
unix_sock_ro_perms = "0777"
# Set the UNIX socket permissions for the R/W socket. This is used
# for full management of VMs
#
# Default allows only root. If PolicyKit is enabled on the socket,
# the default will change to allow everyone (eg, 0777)
#
# If not using PolicyKit and setting group ownership for access
# control, then you may want to relax this too.
unix_sock_rw_perms = "0770"
# Set the UNIX socket permissions for the admin interface socket.
#
# Default allows only owner (root), do not change it unless you are
# sure to whom you are exposing the access to.
#unix_sock_admin_perms = "0700"
# Set the name of the directory in which sockets will be found/created.
#unix_sock_dir = "/var/run/libvirt"
#################################################################
#
# Authentication.
#
# - none: do not perform auth checks. If you can connect to the
# socket you are allowed. This is suitable if there are
# restrictions on connecting to the socket (eg, UNIX
# socket permissions), or if there is a lower layer in
# the network providing auth (eg, TLS/x509 certificates)
#
# - sasl: use SASL infrastructure. The actual auth scheme is then
# controlled from /etc/sasl2/libvirt.conf. For the TCP
# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
# For non-TCP or TLS sockets, any scheme is allowed.
#
# - polkit: use PolicyKit to authenticate. This is only suitable
# for use on the UNIX sockets. The default policy will
# require a user to supply their own password to gain
# full read/write access (aka sudo like), while anyone
# is allowed read/only access.
#
# Set an authentication scheme for UNIX read-only sockets
# By default socket permissions allow anyone to connect
#
# To restrict monitoring of domains you may wish to enable
# an authentication mechanism here
auth_unix_ro = "none"
# Set an authentication scheme for UNIX read-write sockets
# By default socket permissions only allow root. If PolicyKit
# support was compiled into libvirt, the default will be to
# use 'polkit' auth.
#
# If the unix_sock_rw_perms are changed you may wish to enable
# an authentication mechanism here
auth_unix_rw = "none"
# Change the authentication scheme for TCP sockets.
#
# If you don't enable SASL, then all TCP traffic is cleartext.
# Don't do this outside of a dev/test scenario. For real world
# use, always enable SASL and use the GSSAPI or DIGEST-MD5
# mechanism in /etc/sasl2/libvirt.conf
#auth_tcp = "sasl"
# Change the authentication scheme for TLS sockets.
#
# TLS sockets already have encryption provided by the TLS
# layer, and limited authentication is done by certificates
#
# It is possible to make use of any SASL authentication
# mechanism as well, by using 'sasl' for this option
#auth_tls = "none"
# Change the API access control scheme
#
# By default an authenticated user is allowed access
# to all APIs. Access drivers can place restrictions
# on this. By default the 'nop' driver is enabled,
# meaning no access control checks are done once a
# client has authenticated with libvirtd
#
#access_drivers = [ "polkit" ]
#################################################################
#
# TLS x509 certificate configuration
#
# Use of TLS requires that x509 certificates be issued. The default locations
# for the certificate files is as follows:
#
# /etc/pki/CA/cacert.pem - The CA master certificate
# /etc/pki/libvirt/servercert.pem - The server certificate signed with
# the cacert.pem
# /etc/pki/libvirt/private/serverkey.pem - The server private key
#
# It is possible to override the default locations by altering the 'key_file',
# 'cert_file', and 'ca_file' values and uncommenting them below.
#
# NB, overriding the default of one location requires uncommenting and
# possibly additionally overriding the other settings.
#
# Override the default server key file path
#
#key_file = "/etc/pki/libvirt/private/serverkey.pem"
# Override the default server certificate file path
#
#cert_file = "/etc/pki/libvirt/servercert.pem"
# Override the default CA certificate path
#
#ca_file = "/etc/pki/CA/cacert.pem"
# Specify a certificate revocation list.
#
# Defaults to not using a CRL, uncomment to enable it
#crl_file = "/etc/pki/CA/crl.pem"
#################################################################
#
# Authorization controls
#
# Flag to disable verification of our own server certificates
#
# When libvirtd starts it performs some sanity checks against
# its own certificates.
#
# Default is to always run sanity checks. Uncommenting this
# will disable sanity checks which is not a good idea
#tls_no_sanity_certificate = 1
# Flag to disable verification of client certificates
#
# Client certificate verification is the primary authentication mechanism.
# Any client which does not present a certificate signed by the CA
# will be rejected.
#
# Default is to always verify. Uncommenting this will disable
# verification - make sure an IP whitelist is set
#tls_no_verify_certificate = 1
# A whitelist of allowed x509 Distinguished Names
# This list may contain wildcards such as
#
# "C=GB,ST=London,L=London,O=Red Hat,CN=*"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no DN's are checked
#tls_allowed_dn_list = ["DN1", "DN2"]
# A whitelist of allowed SASL usernames. The format for username
# depends on the SASL authentication mechanism. Kerberos usernames
# look like username@REALM
#
# This list may contain wildcards such as
#
# "*@EXAMPLE.COM"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no Username's are checked
#sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ]
# Override the compile time default TLS priority string. The
# default is usually "NORMAL" unless overridden at build time.
# Only set this is it is desired for libvirt to deviate from
# the global default settings.
#
#tls_priority="NORMAL"
#################################################################
#
# Processing controls
#
# The maximum number of concurrent client connections to allow
# over all sockets combined.
#max_clients = 5000
# The maximum length of queue of connections waiting to be
# accepted by the daemon. Note, that some protocols supporting
# retransmission may obey this so that a later reattempt at
# connection succeeds.
#max_queued_clients = 1000
# The maximum length of queue of accepted but not yet
# authenticated clients. The default value is 20. Set this to
# zero to turn this feature off.
#max_anonymous_clients = 20
# The minimum limit sets the number of workers to start up
# initially. If the number of active clients exceeds this,
# then more threads are spawned, up to max_workers limit.
# Typically you'd want max_workers to equal maximum number
# of clients allowed
#min_workers = 5
#max_workers = 20
# The number of priority workers. If all workers from above
# pool are stuck, some calls marked as high priority
# (notably domainDestroy) can be executed in this pool.
#prio_workers = 5
# Limit on concurrent requests from a single client
# connection. To avoid one client monopolizing the server
# this should be a small fraction of the global max_workers
# parameter.
#max_client_requests = 5
# Same processing controls, but this time for the admin interface.
# For description of each option, be so kind to scroll few lines
# upwards.
#admin_min_workers = 1
#admin_max_workers = 5
#admin_max_clients = 5
#admin_max_queued_clients = 5
#admin_max_client_requests = 5
#################################################################
#
# Logging controls
#
# Logging level: 4 errors, 3 warnings, 2 information, 1 debug
# basically 1 will log everything possible
# Note: Journald may employ rate limiting of the messages logged
# and thus lock up the libvirt daemon. To use the debug level with
# journald you have to specify it explicitly in 'log_outputs', otherwise
# only information level messages will be logged.
#log_level = 3
# Logging filters:
# A filter allows to select a different logging level for a given category
# of logs
# The format for a filter is one of:
# x:name
# x:+name
# where name is a string which is matched against the category
# given in the VIR_LOG_INIT() at the top of each libvirt source
# file, e.g., "remote", "qemu", or "util.json" (the name in the
# filter can be a substring of the full category name, in order
# to match multiple similar categories), the optional "+" prefix
# tells libvirt to log stack trace for each message matching
# name, and x is the minimal level where matching messages should
# be logged:
# 1: DEBUG
# 2: INFO
# 3: WARNING
# 4: ERROR
#
# Multiple filters can be defined in a single @filters, they just need to be
# separated by spaces.
#
# e.g. to only get warning or errors from the remote layer and only errors
# from the event layer:
#log_filters="3:remote 4:event"
# Logging outputs:
# An output is one of the places to save logging information
# The format for an output can be:
# x:stderr
# output goes to stderr
# x:syslog:name
# use syslog for the output and use the given name as the ident
# x:file:file_path
# output to a file, with the given filepath
# x:journald
# output to journald logging system
# In all case the x prefix is the minimal level, acting as a filter
# 1: DEBUG
# 2: INFO
# 3: WARNING
# 4: ERROR
#
# Multiple outputs can be defined, they just need to be separated by spaces.
# e.g. to log all warnings and errors to syslog under the libvirtd ident:
#log_outputs="3:syslog:libvirtd"
#
# Log debug buffer size:
#
# This configuration option is no longer used, since the global
# log buffer functionality has been removed. Please configure
# suitable log_outputs/log_filters settings to obtain logs.
#log_buffer_size = 64
##################################################################
#
# Auditing
#
# This setting allows usage of the auditing subsystem to be altered:
#
# audit_level == 0 -> disable all auditing
# audit_level == 1 -> enable auditing, only if enabled on host (default)
# audit_level == 2 -> enable auditing, and exit if disabled on host
#
#audit_level = 2
#
# If set to 1, then audit messages will also be sent
# via libvirt logging infrastructure. Defaults to 0
#
#audit_logging = 1
###################################################################
# UUID of the host:
# Host UUID is read from one of the sources specified in host_uuid_source.
#
# - 'smbios': fetch the UUID from 'dmidecode -s system-uuid'
# - 'machine-id': fetch the UUID from /etc/machine-id
#
# The host_uuid_source default is 'smbios'. If 'dmidecode' does not provide
# a valid UUID a temporary UUID will be generated.
#
# Another option is to specify host UUID in host_uuid.
#
# Keep the format of the example UUID below. UUID must not have all digits
# be the same.
# NB This default all-zeros UUID will not work. Replace
# it with the output of the 'uuidgen' command and then
# uncomment this entry
#host_uuid = "00000000-0000-0000-0000-000000000000"
#host_uuid_source = "smbios"
###################################################################
# Keepalive protocol:
# This allows libvirtd to detect broken client connections or even
# dead clients. A keepalive message is sent to a client after
# keepalive_interval seconds of inactivity to check if the client is
# still responding; keepalive_count is a maximum number of keepalive
# messages that are allowed to be sent to the client without getting
# any response before the connection is considered broken. In other
# words, the connection is automatically closed approximately after
# keepalive_interval * (keepalive_count + 1) seconds since the last
# message received from the client. If keepalive_interval is set to
# -1, libvirtd will never send keepalive requests; however clients
# can still send them and the daemon will send responses. When
# keepalive_count is set to 0, connections will be automatically
# closed after keepalive_interval seconds of inactivity without
# sending any keepalive messages.
#
#keepalive_interval = 5
#keepalive_count = 5
#
# These configuration options are no longer used. There is no way to
# restrict such clients from connecting since they first need to
# connect in order to ask for keepalive.
#
#keepalive_required = 1
#admin_keepalive_required = 1
# Keepalive settings for the admin interface
#admin_keepalive_interval = 5
#admin_keepalive_count = 5
###################################################################
# Open vSwitch:
# This allows to specify a timeout for openvswitch calls made by
# libvirt. The ovs-vsctl utility is used for the configuration and
# its timeout option is set by default to 5 seconds to avoid
# potential infinite waits blocking libvirt.
#
#ovs_timeout = 5

View File

@ -0,0 +1,5 @@
<network>
<name>{{ item.name }}</name>
<forward mode='bridge' />
<bridge name='{{ item.bridge_iface }}' />
</network>

View File

@ -0,0 +1,5 @@
vmhost_required_packages:
- libvirt-daemon-driver-qemu
- python3-libvirt
- python3-lxml
- qemu-kvm

View File

@ -0,0 +1,13 @@
import os
import sys
here = os.path.dirname(__file__)
srcdir = os.path.join(here, 'src')
sys.path.insert(0, srcdir)
import dcow.app
config = os.path.join(here, 'production.ini')
application = dcow.app.Application.create(config)

View File

@ -0,0 +1,3 @@
[gallery]
screenshot_dir = /srv/www/darkchestofwonders.us/screenshots
thumbnail_dir = /srv/www/darkchestofwonders.us/thumbnails

View File

@ -0,0 +1,8 @@
- name: restart httpd
service:
name=httpd
state=restarted
- name: reload httpd
service:
name=httpd
state=reloaded

View File

@ -0,0 +1,75 @@
- name: ensure mod_wsgi is installed
package:
name=python3-mod_wsgi
state=present
notify: restart httpd
tags:
- install
- name: ensure rsync is installed
package:
name=rsync
state=present
tags:
- install
- name: ensure app group exists
group:
name=webapp.dcow
state=present
- name: ensure app user exists
user:
name=webapp.dcow
group=webapp.dcow
home=/srv/www/darkchestofwonders.us
createhome=yes
state=present
- name: ensure app home directory permissions are set
file:
path=/srv/www/darkchestofwonders.us
mode=0755
state=directory
- name: ensure publisher keys are trusted
authorized_key:
key: "{{ dcow_publisher_keys|join('\n') }}"
user: webapp.dcow
exclusive: true
- name: ensure virtualenv exists
become: true
become_user: webapp.dcow
pip:
name: pip
virtualenv: /srv/www/darkchestofwonders.us/venv
virtualenv_command: /usr/bin/python3 -m venv
- name: ensure dcow wsgi script is installed
copy:
src=dcow.wsgi
dest=/srv/www/darkchestofwonders.us/dcow.wsgi
mode=0644
- name: ensure dcow app is configured
copy:
src=production.ini
dest=/srv/www/darkchestofwonders.us/production.ini
mode=0644
- name: ensure screenshot storage directories exist
file:
path=/srv/www/darkchestofwonders.us/{{ item }}
owner=webapp.dcow
group=webapp.dcow
mode=0755
state=directory
with_items:
- screenshots
- thumbnails
- name: ensure apache is configured to serve darkchestofwonders.us
template:
src=darkchestofwonders.us.httpd.conf.j2
dest=/etc/httpd/conf.d/darkchestofwonders.us.conf
mode=0644
notify: reload httpd

View File

@ -0,0 +1,47 @@
WSGIDaemonProcess dcow \
user=webapp.dcow \
group=webapp.dcow \
python-home=/srv/www/darkchestofwonders.us/venv \
lang=en_US.UTF-8 \
display-name=%{GROUP}
<VirtualHost _default_:80>
ServerName darkchestofwonders.us
RewriteEngine On
RewriteRule (.*) https://%{SERVER_NAME}$1 [R=301,L]
</VirtualHost>
<VirtualHost _default_:443>
ServerName darkchestofwonders.us
Include conf.d/ssl.include
SSLCertificateKeyFile /var/lib/letsencrypt/live/darkchestofwonders.us/privkey.pem
SSLCertificateFile /var/lib/letsencrypt/live/darkchestofwonders.us/fullchain.pem
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</IfModule>
WSGIScriptAlias / /srv/www/darkchestofwonders.us/dcow.wsgi \
process-group=dcow
Alias /screenshots /srv/www/darkchestofwonders.us/screenshots
<Location />
Require all granted
</Location>
<Location /upload>
<IfModule auth_gssapi_module>
AuthType GSSAPI
AuthName "{{ krb5_realm|lower }} Domain Authentication"
#KrbServiceName HTTP/{{ ansible_fqdn }}@{{ krb5_realm }}
GssapiCredStore keytab:/etc/httpd/httpd.keytab
GssapiBasicAuth On
Require valid-user
</IfModule>
<IfModule !auth_kerb_module>
Require all denied
</IfModule>
</Location>
</VirtualHost>

View File

@ -0,0 +1,20 @@
# vim: set ft=apache :
WSGIDaemonProcess dchwww \
user=webapp.dchwww \
group=webapp.dchwww \
python-home=/srv/www/dustin.hatch.name/venv \
display-name=%{GROUP}
<VirtualHost *:80>
ServerName dustin.hatch.name
WSGIScriptAlias / /srv/www/dustin.hatch.name/site.py \
process-group=dchwww
Alias /static /srv/www/dustin.hatch.name/static
<Location />
Require all granted
</Location>
</VirtualHost>

View File

@ -0,0 +1,8 @@
- name: restart httpd
service:
name=httpd
state=restarted
- name: reload httpd
service:
name=httpd
state=reloaded

View File

@ -0,0 +1,53 @@
- name: ensure mod_wsgi is installed
package:
name=python3-mod_wsgi
state=present
notify: restart httpd
tags:
- install
- name: ensure rsync is installed
package:
name=rsync
state=present
tags:
- install
- name: ensure app group exists
group:
name=webapp.dchwww
state=present
- name: ensure app user exists
user:
name=webapp.dchwww
group=webapp.dchwww
home=/srv/www/dustin.hatch.name
createhome=yes
state=present
- name: ensure app home directory permissions are set
file:
path=/srv/www/dustin.hatch.name
mode=0755
state=directory
- name: ensure publisher keys are trusted
authorized_key:
key: "{{ dchwww_publisher_keys|join('\n') }}"
user: webapp.dchwww
exclusive: true
- name: ensure virtualenv exists
become: true
become_user: webapp.dchwww
pip:
name: pip
virtualenv: /srv/www/dustin.hatch.name/venv
virtualenv_command: /usr/bin/python3 -m venv
- name: ensure apache is configured to serve dustin.hatch.name
copy:
src=dustin.hatch.name.httpd.conf
dest=/etc/httpd/conf.d/dustin.hatch.name.conf
mode=0644
notify: reload httpd

View File

@ -0,0 +1,9 @@
<VirtualHost _default_:80>
ServerName ebonfire.com
ServerAlias www.ebonfire.com
DocumentRoot /srv/www/ebonfire.com/htdocs
<Directory /srv/www/ebonfire.com/htdocs>
Require all granted
</Directory>
</VirtualHost>

View File

@ -0,0 +1,4 @@
- name: reload httpd
service:
name=httpd
state=reloaded

View File

@ -0,0 +1,37 @@
- name: ensure rsync is installed
package:
name=rsync
state=present
tags:
- install
- name: ensure app group exists
group:
name=webapp.ebonfire
state=present
- name: ensure app user exists
user:
name=webapp.ebonfire
group=webapp.ebonfire
home=/srv/www/ebonfire.com
createhome=yes
state=present
- name: ensure app home directory permissions are set
file:
path=/srv/www/ebonfire.com
mode=0755
state=directory
- name: ensure publisher keys are trusted
authorized_key:
key: "{{ ebonfire_publisher_keys|join('\n') }}"
user: webapp.ebonfire
exclusive: true
- name: ensure apache is configured to serve ebonfire.com
copy:
src=ebonfire.com.httpd.conf
dest=/etc/httpd/conf.d/ebonfire.com.conf
mode=0644
notify: reload httpd

View File

@ -0,0 +1,9 @@
<VirtualHost _default_:80>
ServerName nratonpass.com
ServerAlias www.nratonpass.com
DocumentRoot /srv/www/nratonpass.com/htdocs
<Directory /srv/www/nratonpass.com/htdocs>
Require all granted
</Directory>
</VirtualHost>

View File

@ -0,0 +1,4 @@
- name: reload httpd
service:
name=httpd
state=reloaded

View File

@ -0,0 +1,37 @@
- name: ensure rsync is installed
package:
name=rsync
state=present
tags:
- install
- name: ensure app group exists
group:
name=webapp.nratonpass
state=present
- name: ensure app user exists
user:
name=webapp.nratonpass
group=webapp.nratonpass
home=/srv/www/nratonpass.com
createhome=yes
state=present
- name: ensure app home directory permissions are set
file:
path=/srv/www/nratonpass.com
mode=0755
state=directory
- name: ensure publisher keys are trusted
authorized_key:
key: "{{ nratonpass_publisher_keys|join('\n') }}"
user: webapp.nratonpass
exclusive: true
- name: ensure apache is configured to serve nratonpass.com
copy:
src=nratonpass.com.httpd.conf
dest=/etc/httpd/conf.d/nratonpass.com.conf
mode=0644
notify: reload httpd

View File

@ -4,3 +4,6 @@ winbind_use_default_domain: true
winbind_offline_login: true
winbind_kerberos_method: secrets and keytab
winbind_refresh_tickets: false
winbind_join_username: ''
winbind_join_password: ''

View File

@ -0,0 +1,104 @@
#!/usr/bin/python
import os
import subprocess
class JoinFailed(Exception):
pass
def _make_env():
env = os.environ.copy()
for k in list(env.keys()):
if k == 'LANG' or k.startswith('LC_'):
del env[k]
env['LANG'] = 'en_US.UTF-8'
return env
def is_domain_member():
cmd = ['net', 'ads', 'status', '-P']
with open(os.devnull, 'w+') as null:
p = subprocess.Popen(cmd, stdin=null, stdout=null, stderr=null)
return p.wait() == 0
def join_domain(username, password):
cmd = ['net', 'ads', 'join', '-U', username]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=_make_env(),
)
output = p.communicate(password.encode('utf-8'))
if p.wait() != 0:
raise JoinFailed(output.decode('utf-8'))
def leave_domain(username, password):
cmd = ['net', 'ads', 'leave', '-U', username]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=_make_env(),
)
output = p.communicate(password.encode('utf-8'))
if p.wait() != 0:
raise JoinFailed(output.decode('utf-8'))
def main():
module = AnsibleModule(
argument_spec=dict(
username=dict(
required=True,
),
password=dict(
required=True,
no_log=True,
),
state=dict(
choices=[
'joined',
'unjoined',
],
default='joined',
)
),
supports_check_mode=True,
)
username = module.params['username']
password = module.params['password']
state = module.params['state']
changed = False
if is_domain_member():
if state == 'unjoined':
changed = True
if not module.check_mode:
if not password:
module.fail_json(msg='Need password to leave domain')
try:
leave_domain(username, password)
except JoinFailed as e:
module.fail_json(message=e.args[0])
elif state == 'joined':
changed = True
if not module.check_mode:
if not password:
module.fail_json(msg='Need password to join domain')
try:
join_domain(username, password)
except JoinFailed as e:
module.fail_json(message=e.args[0])
module.exit_json(changed=changed)
from ansible.module_utils.basic import *
main()

View File

@ -36,3 +36,9 @@
template:
src=default-realm.krb5.conf.j2
dest=/etc/krb5.conf.d/default-realm.conf
- name: ensure machine is a member of the domain
ads_member:
username: '{{ winbind_join_username }}'
password: '{{ winbind_join_password }}'
state: joined

4
vmhost.yml Normal file
View File

@ -0,0 +1,4 @@
- hosts: vm-hosts
roles:
- vmhost
- dch-storage-net

13
websites.yml Normal file
View File

@ -0,0 +1,13 @@
- hosts: public-web
roles:
- apache
- certbot
- websites/dustin.hatch.name
- websites/ebonfire.com
- websites/nratonpass.com
- websites/darkchestofwonders.us
tasks:
- name: ensure httpd service is running
service:
name=httpd
state=started