Skip to content

Commit

Permalink
Add: Basic ansible playbook for configuring new caching content servers
Browse files Browse the repository at this point in the history
  • Loading branch information
LordAro committed Nov 17, 2020
1 parent 6ba7e83 commit 65cc127
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 0 deletions.
11 changes: 11 additions & 0 deletions ansible/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Extremely basic instructions for using ansible

Requirements:
* Public ssh keys to authorized_keys of the debian user on all content servers

Then run:

```
ansible-galaxy install -r requirements.yml
ansible-playbook --user debian --inventory inventory content-servers.yml
```
174 changes: 174 additions & 0 deletions ansible/content-servers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
- hosts: bananas_fileservers
gather_facts: true
become: true

vars:
# Our vars, for easy reuse
cache_timeout: "1y" # Basically just as long as nginx runs for
bananas_server: bananas.openttd.org
bananas_cdn_server: bananas.cdn.openttd.org
bananas_server_secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
36643134646634303835373564336465653938376530363333353830306134336461333730633662
3139636438373063306331386339366331343231383766390a306634346539353361336431393662
66313332353438623662653138333239623330613361613837346162373261626266646631653835
3162343533373631360a376136363233313937333032356137353934373536616164373166633065
30353033393436663230363436356265363739663266363034326263356163326264
nginx_shared_config: |
location = /healthz {
access_log off;
return 200;
}
# Rewrite the first to the second:
# base-graphics/12345678/12345678901234567890123456789012/filename.tar.gz
# base-graphics/12345678/12345678901234567890123456789012.tar.gz
# This allows the OpenTTD client to know the name to use for the file,
# while the S3 only knows the md5sum based name.
location / {
rewrite "^/([a-z-]+)/([a-f0-9]{8})/([a-f0-9]{32})/[a-zA-Z0-9-_.]+\.tar\.gz$" $1/$2/$3.tar.gz break;
return 404;
proxy_pass https://{{ bananas_cdn_server }}/;
proxy_hide_header Strict-Transport-Security;
proxy_cache nginx-cache;
proxy_cache_valid 200 {{ cache_timeout }};
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_revalidate on;
proxy_cache_lock on;
proxy_ignore_headers Set-Cookie;
add_header X-Cache-Status $upstream_cache_status;
}
# Role config vars
certbot_admin_email: info@openttd.org
certbot_create_if_missing: true
certbot_create_standalone_stop_services: []
certbot_certs:
- domains:
- "{{ inventory_hostname }}"
nginx_extra_http_options: |
proxy_cache_path /tmp/nginx-cache/ levels=1:2 keys_zone=nginx-cache:16m max_size=1g inactive={{ cache_timeout }} use_temp_path=off;
nginx_remove_default_vhost: true
nginx_vhosts:
- listen: "80"
server_name: "{{ inventory_hostname }}"
filename: "{{ inventory_hostname }}.80.conf"
extra_parameters: |
{{ nginx_shared_config }}
- listen: "443 ssl http2"
server_name: "{{ inventory_hostname }}"
filename: "{{ inventory_hostname }}.443.conf"
# Config partially taken from https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.6
extra_parameters: |
ssl_certificate /etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
{{ nginx_shared_config }}
pre_tasks:
- name: Update & upgrade & cleanup apt.
apt:
update_cache: true
upgrade: safe
autoremove: yes
autoclean: yes
cache_valid_time: 86400 # a day is plenty
changed_when: false

- name: Install apt https support & cron.
apt:
name:
- apt-transport-https
- cron # required for certbot
state: present

roles:
- geerlingguy.certbot
- geerlingguy.nginx

tasks:
- name: Flush handlers in case any configs have changed.
meta: flush_handlers

# Tests basic nginx
- name: Test secure connection to SSL domain.
uri:
url: https://{{ inventory_hostname }}/healthz
status_code: 200
delegate_to: localhost
become: false

# Tests base path
- name: Test secure connection to SSL domain.
uri:
url: https://{{ inventory_hostname }}/
status_code: 404
delegate_to: localhost
become: false

- name: Install some helpful utilities.
apt:
name:
- bash-completion
- logrotate
- molly-guard
- rsync
- sshguard
- unattended-upgrades
- vim
state: present

- name: Copy sshd config.
copy:
src: files/sshd_config
dest: /etc/ssh/sshd_config
notify:
restart ssh

- name: Enable persistent systemd journal.
lineinfile:
path: /etc/systemd/journald.conf
regexp: "Storage="
line: "Storage=persistent"

- name: Add FQDN to /etc/hosts.
lineinfile:
path: /etc/hosts
regexp: "127.0.1.1"
line: "127.0.1.1 {{ inventory_hostname }} {{ inventory_hostname_short }}"

# bananas-notifier
# TODO: Consider splitting this out into a separate role
- name: Install bananas-notifier dependencies.
apt:
name:
- python3
- python3-requests

- name: Install bananas-notifier.py
copy:
src: files/bananas-notifier.py
dest: /usr/local/bin/bananas-notifier.py

# Don't need this just yet
#- name: Install cronjob
# cron:
# minute: "*/5" # every 5 mins
# name: bananas-notifier
# job: python3 /usr/local/bin/bananas-notifier.py {{ bananas_server }} {{ bananas_server_secret }}
# no_log: true # hide secret

handlers:
- name: restart ssh
service:
name: ssh
state: restarted
27 changes: 27 additions & 0 deletions ansible/files/bananas-notifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3

import socket
import sys

import requests


if len(sys.argv) != 3:
print("Incorrect number of arguments provided", file=sys.stderr)
print(f"Expected {sys.argv[0]} bananas_server bananas_server_secret", file=sys.stderr)
sys.exit(1)

bananas_server = sys.argv[1]
bananas_server_secret = sys.argv[2]

self_hostname = socket.getfqdn()

# Note: Checks HTTP only
if requests.get(f"http://{self_hostname}/healthz").status_code != 200:
print("NGINX does not appear to be running :(", file=sys.stderr)
sys.exit(2)

requests.post(
"https://{bananas_server}/update_fileserver",
data={"hostname": self_hostname, "secret": bananas_server_secret},
)
33 changes: 33 additions & 0 deletions ansible/files/sshd_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copied from https://infosec.mozilla.org/guidelines/openssh.html

# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key

KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

# Password based logins are disabled - only public key based logins are allowed.
AuthenticationMethods publickey

# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE

# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO

# Root login is not allowed for auditing reasons. This is because it's difficult to track which process belongs to which root user:
#
# On Linux, user sessions are tracking using a kernel-side session id, however, this session id is not recorded by OpenSSH.
# Additionally, only tools such as systemd and auditd record the process session id.
# On other OSes, the user session id is not necessarily recorded at all kernel-side.
# Using regular users in combination with /bin/su or /usr/bin/sudo ensure a clear audit track.
PermitRootLogin No

# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
UsePrivilegeSeparation sandbox
3 changes: 3 additions & 0 deletions ansible/inventory
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[bananas_fileservers]
bananas-1.cdn.openttd.org
bananas-2.cdn.openttd.org
4 changes: 4 additions & 0 deletions ansible/requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- name: geerlingguy.certbot
version: "3.1.0"
- name: geerlingguy.nginx
version: "2.8.0"

0 comments on commit 65cc127

Please sign in to comment.