Commit Graph

448 Commits (284fb569a25a7ece2e54c0e9bc7d2a7c5b06b180)

Author SHA1 Message Date
Dustin 284fb569a2 ci: Add pipeline for Graylog 2021-01-31 15:34:36 -06:00
Dustin 7f8a9ce114 roles/graylog: Update Graylog repository RPM URL
Graylog 3.3 is currently installed on logs0.  Attempting to install the
*graylog-3.1-repository* package causes a transaction conflict, making
the task and playbook fail.
2021-01-31 15:33:42 -06:00
Dustin ee93586a95 roles/apache: Add previously-ignored cert symlinks
Before the advent of `ansible-vault`, and  long before `certbot`/`lego`,
I used to keep certificate files (and especially private key files) out
of the Git repository.  Now that certificates are stored in a separate
repository, and only symlinks are stored in the configuration policy,
this no longer makes any sense.  In particular, it prevents the continuous
enforcement process from installing Let's Encrypt certificates that have
been automatically renewed.
2021-01-24 17:08:00 -06:00
Dustin 7d740079c8 roles/ssh-hostkeys: Remove duplicate keys for git0 2020-12-30 22:13:47 -06:00
Dustin cd577a555e ci: Add pipeline for Synapse (Matrix) 2020-12-30 22:12:54 -06:00
Dustin 5a114eecf0 websites/proxy-matrix: Add Synapse rev proxy setup
The *websites/proxy-matrix* role configures the Internet-facing reverse
proxy to handle the *hatch.chat* domain.  Most Matrix communication
happens over the default HTTPS port, and as such will be directed
through the reverse proxy.
2020-12-30 22:05:26 -06:00
Dustin 2df1605421 hosts: Add matrix0.p.b
*matrix0.pyrocufflink.blue* hosts the Matrix homeserver for
*hatch.chat*.
2020-12-30 22:04:51 -06:00
Dustin 371305bed4 roles/synapse: Deploy the Matrix homeserver
The *synapse* role and the corresponding `synapse.yml` playbook deploy
Synapse, the reference Matrix homeserver implementation.

Deploying Synapse itself is fairly straightforward: it is packaged by
Fedora and therefore can simply be installed via `dnf` and started by
`systemd`.  Making the service available on the Internet, however, is
more involved.  The Matrix protocol mostly works over HTTPS on the
standard port (443), so a typical reverse proxy deployment is mostly
sufficient.  Some parts of the Matrix protocol, however, involve
communication over an alternate port (8448).  This could be handled by a
reverse proxy as well, but since it is a fairly unique port, it could
also be handled by NAT/port forwarding.  In order to support both
deployment scenarios (as well as the hypothetical scenario wherein the
Synapse machine is directly accessible from the Internet), the *synapse*
role supports specifying an optional `matrix_tls_cert` variable.  If
this variable is set, it should contain the path to a certificate file
on the Ansible control machine that will be used for the "direct"
connections (i.e. on port 8448).  If it is not set, the default Apache
certificate will be used for both virtual hosts.

Synapse has a pretty extensive configuration schema, but most of the
options are set to their default values by the *synapse* role.  Other
than substituting secret keys, the only exposed configuration option is
the LDAP authentication provider.
2020-12-30 21:54:02 -06:00
Dustin d0bf4f9893 ci: Add pipeline for motionEye 2020-12-30 21:06:22 -06:00
Dustin 2da26d9bf6 roles/bitwarden_rs: Ensure docker service runs
Since the *bitwarden_rs* relies on Docker for distribution and process
management (at least for now), it needs to ensure that the `docker`
service starts automatically.
2020-12-30 21:02:32 -06:00
Dustin f9e8c78e5a roles/websites: Set authorized_keys file perms
Because the various "webapp.*" users' home directories are under
`/srv/www`, the default SELinux context type is `httpd_sys_content_t`.
The SSH daemon is not allowed to read files with this label, so it
cannot load the contents of these users' `authorized_keys` files.  To
address this, we have to explicitly set the SELinux type to
`ssh_home_t`.
2020-12-30 20:59:27 -06:00
Dustin c92af29e84 roles/named: Send application logs to syslog
BIND sends its normal application logs (as opposed to query logs) to the
`default_debug` channel.  By sending these log messages to syslog, they
can be routed and rotated using the normal system policies.  Using a
separate dedicated log file just ends up consuming a lot of space, as it
is not managed by any policy.
2020-12-26 11:36:15 -06:00
Dustin 59e8244a08 roles/apache: Add tags to tasks
Adding tags to tasks makes them easier to run in isolation.
2020-12-26 11:35:45 -06:00
Dustin aa1ab75edd roles/apache: logrotate: Compress logs immediately
To conserve space on the log volume of web servers, "old" log files are
now compressed immediately, as opposed to waiting until the next
rotation.
2020-12-26 11:33:09 -06:00
Dustin b519f97f6a roles/apache: Disable ssl_request_log
I am not sure the point of having both `ssl_request_log` and
`ssl_access_log`.  The former includes the TLS ciphers used in the
connection, which is not particularly interesting information.  To save
space on the log volume of web servers using Apache, we should just stop
creating this log file.
2020-12-26 11:31:24 -06:00
Dustin d1cdc8bfc3 roles/cert: Add handler topic notification
Changing/renewing a certificate generally requires restarting or
reloading some service.  Since the *cert* role is intended to be generic
and reusable, it naturally does not know what action to take to effect
the change.  It works well for the initial deployment of a new
application, since the service is reloaded anyway in order for the new
configuration to be applied.  It fails, however, for continuous
enforcement, when a certificate is renewed automatically (i.e. by
`lego`) but no other changes are being made.  This has caused a number
of disruptions when some certificate expires and its replacement is
available but has not yet been loaded.

To address this issue, I have added a handler "topic" notification to
the *certs* role.  When either the certificate or private key file is
replaced, the relevant task will "notify" a generic handler "topic."
This allows some other role to define a specific handler, which
"listens" for these notifications, and takes the appropriate action for
its respective service.

For this mechanism to work, though, the *cert* role can only be used as
a dependency of another role.  That role must define the handler and
configure it to listen to the generic "certificate changed" topic.  As
such, each of the roles that are associated with a certificate deployed
by the *cert* role now declare it as a dependency, and the top-level
playbooks only include those roles.
2020-12-26 10:38:17 -06:00
Dustin 8a18c92730 roles/collectd-prometheus: Configure plugin
The *collectd-prometheus* role configures the *write_prometheus* plugin
for collectd.  This plugin exposes data collected or received by the
collectd process in the Prometheus Exposition Format over HTTP.  It
provides the same functionality as the "official" collectd Exporter
maintained by the Prometheus team, but integrates natively into the
collectd process, and is much more complete.

The main intent of this role is to provide a mechanism to combine the
collectd data from all Pyrocufflink hosts and insert it into Prometheus.
By configuring the collectd instance on the Prometheus server itself to
enable and use the *write_prometheus* plugin and to receive the
multicast data from other hosts, collectd itself provides the desired
functionality.
2020-12-26 09:44:04 -06:00
Dustin b6650e4067 ci: collectd: fix syntax error 2020-12-26 09:39:28 -06:00
Dustin 621035e89b Merge branch 'collectd' into master 2020-12-23 21:26:01 -06:00
Dustin 8e180d00ab collectd: Ensure service is enabled 2020-12-23 21:25:49 -06:00
Dustin debf7d8e5a hosts: Add pyrocufflink to collectd group
We want collectd deployed on all production machines.
2020-12-23 21:04:49 -06:00
Dustin 71f55ddfdf hosts: hass1: Set collectd network interface
Because *hass1.pyrocufflink.blue* has multiple interfaces, collectd does
not know which interface it should use to send multicast metrics
messages.  To force it to use the wired interface, which is connected to
the default internal ("blue") network, the `interface` property needs to
be set.
2020-12-23 20:57:01 -06:00
Dustin 8d442b2aaf roles/collectd: Support setting server interface
For hosts with multiple network interfaces, collectd may not send
multicast messages through the correct interface.  To ensure that it
does, the `Interface` configuration option can be specified with each
`Server` option.  To define this option, entries in the
`collectd_network_servers` list can now have an `interface` property.
2020-12-23 20:54:48 -06:00
Dustin 19f0d713f4 hosts: Move koji0.p.b to offline
I doubt I will be using Koji much if at all any more.  In preparation
for decommissioning it, I am moving the Koji inventory to hosts.offline,
to prevent Jenkins jobs from failing.
2020-12-13 09:54:01 -06:00
Dustin 4a4f984f1f ci: Add Jenkins pipeline for collectd 2020-12-08 21:26:43 -06:00
Dustin cbbef24bbd collectd: Install and configure collectd
The *collectd* role, with its corresponding `collectd.yml` playbook,
installs *collectd* onto the managed node and manages basic
configuration for it.  By default, it will enable several plugins,
including the `network` plugin.  The `collectd_disable_plugins` variable
can be set to a list names of plugins that should NOT be enabled.

The default configuration for the `network` plugin instructs *collectd*
to send metrics to the default IPv6 multicast group.  Any host that has
joined this group and is listening on the specified UDP port (default
25826) can receive the data.  This allows for nearly zero configuration,
as the configuration does not need to be updated if the name or IP
address of the receiver changes.

This configuration is ready to be deployed without any variable changes
to all Pyrocufflink servers.  Once *collectd* is running on the servers,
we can set up a *collectd* instance to receive the data and store them
in a time series database (i.e. Prometheus).
2020-12-08 21:11:27 -06:00
Dustin 750cc8afd4 roles/logrotate: Install and enable logrotate
Since Apache HTTPD does not have any built-in log rotation capability,
we need `logrotate`.  Somewhere along the line, the *logrotate* package
stopped being installed by default.  Additionally, with Fedora 30, it
changed from including a drop-in file for (Ana)cron to providing a
systemd timer unit.

The *logrotate* role will ensure that the *logrotate* package is
installed, and that the *logrotate.timer* service is enabled and
running.  This in turn will ensure that `logrotate` runs daily.  Of
course, since the systemd units were added in Fedora 30, machines to
which this role is applied must be running at least that version.

By listing the *logrotate* role as a dependency of the *httpd* role, we
can ensure that `logrotate` manages the Apache error and access log
files on any server that runs Apache HTTPD.
2020-12-08 20:59:40 -06:00
Dustin 1e42959863 roles/bitwarden_rs: Update to new Docker image
The bitwarden_rs team now maintains its Docker images under the
*bitwardenrs* namespace on Docker Hub.
2020-11-13 06:52:56 -06:00
Dustin 132689a3b8 roles/protonvpn: Set infinite keying retries
By default, strongSwan will only attempt key negotiation once and then
give up.  If the VPN connection is closed because of a network issue, it
is unlikely that a single attempt to reconnect will work, so let's keep
trying until it succeeds.
2020-10-10 11:10:12 -05:00
Dustin 3a36d6b7ff hosts: Add motion0.p.b
*motion0.pyrocufflink.blue* hosts motionEye
2020-10-03 11:30:38 -05:00
Dustin ef4e769ed2 motioneye: Deploy motionEye camera software
The *motioneye* role installs motionEye on a Fedora machine using `pip`.
It configures Apache to proxy for motionEye for outside (HTTPS) access.

The official installation instructions and default configuration for
motionEye assume it will be running as root.  There is, however, no
specific reason for this, as it works just fine as an unprivileged user.
The only minor surprise is that the `conf_path` configuration setting
must be writable, as this is where motionEye places generated
configuration for `motion`.  This path does not, however, have to
include the `motioneye.conf` file itself, which can still be read-only.
2020-10-03 11:29:39 -05:00
Dustin 1c575c4340 protonvpn: Connect to server by IP address
Since DNS only allowed to be sent over the VPN, it is not possible to
resolve the VPN server name unless the VPN is already connected.  This
naturally creates a chicken-and-egg scenario, which we can resolve by
manually providing the IP address of the server we want to connect to.
2020-09-23 18:50:06 -05:00
Dustin 53bc4eac6d ci: Add pipeline for Pyrocufflink DNS 2020-09-06 11:10:50 -05:00
Dustin 8ca093050b pyrocufflink-dns: Cloudflare over ProtonVPN
This commit adds a new playbook, `protonvpn.yml`, and its supporting
roles *strongswan-swanctl* and *protonvpn*.  This playbook configures
strongSwan to connect to ProtonVPN using IPsec/IKEv2.

With this playbook, we configure the name servers on the Pyrocufflink
network to route all DNS requests through the Cloudflare public DNS
recursive servers at 1.1.1.1/1.0.0.1 over ProtonVPN.  Using this setup,
we have the benefit of the speed of using a public DNS server (which is
*significantly* faster than running our own recursive server, usually by
1-2 seconds per request), and the benefit of anonymity from ProtonVPN.

Using the public DNS server alone is great for performance, but allows
the server operator (in this case Cloudflare) to track and analyze usage
patterns.  Using ProtonVPN gives us anonymity (assuming we trust
ProtonVPN not to do the very same tracking), but can have a negative
performance impact if its used for all Internet traffic.  By combining
these solutions, we can get the benefits of both!
2020-09-06 11:06:58 -05:00
Dustin a7b8e2fbfa pyrocufflink-dhcp: Remove obsolete networks
* pyrocufflink.jazz has been gone for a while now
* tachyglossus.net DHCP is managed by the USG now
2020-09-06 10:40:27 -05:00
Dustin f536c9633e roles/named: Support logging queries to syslog
This commit adds two new variables to the *named* role:
`named_queries_syslog` and `named_rpz_syslog`.  These variables control
whether BIND will send query and RPZ log messages to the local syslog
daemon, respectively.
2020-09-06 10:40:27 -05:00
Dustin 84313601ef roles/named: Implement response policy zones
BIND response policy zones (RPZ) support provides a mechanism for
overriding the responses to DNS queries based on a wide range of
criteria.  In the simplest form, a response policy zone can be used to
provide different responses to different clients, or "block" some DNS
names.

For the Pyrocufflink and related networks, I plan to use an RPZ to
implement ad/tracker blocking.  The goal will be to generate an RPZ
definition from a collection of host lists (e.g. those used by uBlock
Origin) periodically.

This commit introduces basic support for RPZ configuration in the
*named* role.  It can be activated by providing a list of "response
policy" definitions (e.g. `zone "name"`) in the `named_response_policy`
variable, and defining the corresponding zones in `named_zones`.
2020-09-06 10:40:01 -05:00
Dustin 44404950c1 Merge branch 'graylog' into master 2020-08-31 20:17:12 -05:00
Dustin 451df9042c ci: Add Jenkins pipeline for Home Assistant 2020-08-29 14:34:50 -05:00
Dustin 40c8df1b13 hosts: cloud0: Configure backups with BURP
Back up `/var/www/html`.
2020-08-29 14:22:17 -05:00
Dustin da3eb1aaf0 hosts: hass1: Configure backups with BURP
Back up `/var/lib/homeassistant`.
2020-08-29 14:22:17 -05:00
Dustin 7b49309803 hassdb: Fix playbook
* Need to apply the *postgresql-server* role to ensure PostgreSQL is
  properly configured
* Need to supply a PostgreSQL certificate (use Let's Encrypt so we don't
  have to manage a CA)
* Missing Ansible Vault file that includes the DB user password
2020-08-29 14:22:17 -05:00
Dustin 9ef88da95f hosts: hassdb0: Add missing vars file 2020-08-29 14:01:50 -05:00
Dustin 8958071edb ci: pyrocufflink: Use pipeline library 2020-08-29 09:12:48 -05:00
Dustin 276ac7e5fb Add rw-root group
Some hosts, such as the Raspberry Pis built using default Fedora images,
do not have proper filesystem separation, but use a single volume for
the entire filesystem.  These hosts cannot have the root filesystem
mounted read-only, since all the writable data are also stored there.

When Jenkins runs configuration policy jobs, it always tries to remount
the root filesystem as read-only on every machine that it configured.
For these hosts with a single volume, this step fails, causing the job
to be marked as failed.  To avoid this, I have added a new group,
*rw-root*; hosts in this group will be omitted from the final remount
step.
2020-08-29 08:53:28 -05:00
Dustin b32b4a2c99 roles/ssh-hostkeys: Add missing host keys
Several new hosts did not have recorded SSH host keys:

* build1-aarch64
* build2-armv7hl
* hass1
* hassdb0
2020-08-28 21:17:02 -05:00
Dustin c7e4810abd hosts: Move burp0, taiga0 to offline
These machines are deprecated.  burp1 has replaced burp0. Nextcloud Deck
seems to be just as useful as Taiga.
2020-08-28 21:13:59 -05:00
Dustin 6ebe9b9a20 ci: Always skip tasks tagged "install"
Software should never be installed or updated by the continuous
enforcement jobs.  This can cause unexpected outages or other problems
if applications or libraries unexpectedly.  Everything should already be
installed and in production before continuous enforcement begins, so
skipping install steps should not matter.

Most tasks that install software are tagged with the `install` tag.
When Jenkins runs `ansible-playbook` to apply configuration policy, it
will now skip any task that includes this tag.
2020-07-24 11:56:49 -05:00
Dustin 0f73b09e09 hosts: Add hassdb0.p.b
*hassdb0.pyrocufflink.blue* hosts the PostgreSQL database for Home
Assistant.
2020-07-14 11:38:44 -05:00
Dustin f1b4598601 roles/hassdb: Deploy Home Assistant database
Normally, Home Assistant uses a SQLite database for storing state
history.  On a Raspberry Pi with only an SD card for storage like
*hass1.pyrocufflink.blue*, this can become extremely slow, especially
for large data sets.  To speed up features like history and logbook,
Home Assistant supports using an external database engine such as
PostgreSQL or MariaDB.

The *hassdb* role and corresponding `hassdb.yml` playbook deploys a
PostgreSQL server for Home Assistant to use.  It needs only to create
the role and database, as Home Assistant manages its own schema.
2020-07-14 11:38:30 -05:00