summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules12
-rw-r--r--Vagrantfile16
-rw-r--r--ansible.cfg8
-rw-r--r--group_vars/all/borgbackup.yml6
-rw-r--r--group_vars/all/unattended-upgrades.yml9
-rw-r--r--hosts3
-rw-r--r--playbooks/borg1.yml26
-rw-r--r--playbooks/nyarlathotep.yml6
-rw-r--r--roles/borgbackup/defaults/main.yml8
-rw-r--r--roles/borgbackup/tasks/main.yml70
-rw-r--r--roles/dotfiles/tasks/main.yml30
m---------roles/enable-standard-cronjobs0
-rw-r--r--roles/gitolite/defaults/main.yml7
-rw-r--r--roles/gitolite/tasks/init.yml18
-rw-r--r--roles/gitolite/tasks/main.yml40
-rw-r--r--roles/gitolite/templates/gitolite.rc.j2196
-rw-r--r--roles/nginx/defaults/main.yml2
-rw-r--r--roles/nginx/files/certbot-renewal.service7
-rw-r--r--roles/nginx/files/certbot-renewal.timer10
-rw-r--r--roles/nginx/handlers/main.yml10
-rw-r--r--roles/nginx/tasks/main.yml36
-rw-r--r--roles/nginx/templates/letsencrypt.conf5
-rw-r--r--roles/nginx/templates/nginx.conf.j229
-rw-r--r--roles/nginx/templates/sslsettings.conf18
m---------roles/postfix0
m---------roles/teamspeak0
m---------roles/unattended-upgrades0
28 files changed, 573 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8000dd9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.vagrant
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..4dbd8bd
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "roles/enable-standard-cronjobs"]
+ path = roles/enable-standard-cronjobs
+ url = https://github.com/Yannik/ansible-role-enable-standard-cronjobs.git
+[submodule "roles/unattended-upgrades"]
+ path = roles/unattended-upgrades
+ url = https://github.com/jnv/ansible-role-unattended-upgrades.git
+[submodule "roles/postfix"]
+ path = roles/postfix
+ url = https://github.com/Oefenweb/ansible-postfix.git
+[submodule "roles/teamspeak"]
+ path = roles/teamspeak
+ url = https://github.com/Tharre/ansible-teamspeak
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..86adde9
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,16 @@
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "debian/stretch64"
+ config.vm.network :private_network, ip: "192.168.33.99"
+
+ config.vm.provision "ansible" do |ansible|
+ ansible.verbose = "v"
+ ansible.skip_tags = "dhparam"
+ ansible.extra_vars = {
+ nginx_disable_ssl: true
+ }
+ ansible.playbook = "playbooks/borg1.yml"
+ end
+
+ config.vm.synced_folder ".", "/vagrant" #, type: "nfs"
+end
diff --git a/ansible.cfg b/ansible.cfg
new file mode 100644
index 0000000..ce3e733
--- /dev/null
+++ b/ansible.cfg
@@ -0,0 +1,8 @@
+[defaults]
+inventory = hosts
+roles_path = roles
+deprecation_warnings = False
+retry_files_enabled = False
+
+[ssh_connection]
+pipelining = True
diff --git a/group_vars/all/borgbackup.yml b/group_vars/all/borgbackup.yml
new file mode 100644
index 0000000..d716a4c
--- /dev/null
+++ b/group_vars/all/borgbackup.yml
@@ -0,0 +1,6 @@
+---
+
+borg_auth_users:
+ - host: xultrabook
+ #key: "{{ lookup('file', '~/etc/ssh_keys.pub') }}"
+ key: "{{ lookup('file', '/var/lib/borg_key.pub') }}"
diff --git a/group_vars/all/unattended-upgrades.yml b/group_vars/all/unattended-upgrades.yml
new file mode 100644
index 0000000..7310950
--- /dev/null
+++ b/group_vars/all/unattended-upgrades.yml
@@ -0,0 +1,9 @@
+---
+
+unattended_origins_patterns:
+ - 'origin=Debian,codename=${distro_codename},label=Debian-Security'
+ - 'origin=Debian,codename=${distro_codename},label=Debian'
+unattended_mail: 'tharre3@gmail.com'
+unattended_remove_unused_dependencies: true
+unattended_automatic_reboot: true
+unattended_automatic_reboot_time: '12:00'
diff --git a/hosts b/hosts
new file mode 100644
index 0000000..0bc8e8e
--- /dev/null
+++ b/hosts
@@ -0,0 +1,3 @@
+[servers]
+borg1.th73.ovh ansible_user=root
+nyarlathotep.th73.ovh ansible_user=tharre
diff --git a/playbooks/borg1.yml b/playbooks/borg1.yml
new file mode 100644
index 0000000..b183e79
--- /dev/null
+++ b/playbooks/borg1.yml
@@ -0,0 +1,26 @@
+---
+- name: Install borg1 server
+ hosts: borg1.th73.ovh
+ gather_facts: False
+ become: true
+ pre_tasks:
+ - raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
+ register: raw_output
+ changed_when: raw_output.stdout != ""
+ tags: always
+ - setup: # gather_facts
+ tags: always
+ tasks:
+ - name: Ensure cron is installed
+ package:
+ name: "cron"
+ state: present
+ tags: ['debian']
+ roles:
+ - { role: dotfiles, tags: ['dotfiles'] }
+ - { role: teamspeak, tags: ['ts3'] }
+ - { role: enable-standard-cronjobs, tags: ['debian'] }
+ - { role: unattended-upgrades, tags: ['debian'] }
+ - { role: postfix, tags: ['debian'] }
+ - { role: gitolite, git_config_keys: ".*", tags: ['git'] }
+ - { role: borgbackup, tags: ['backup'] }
diff --git a/playbooks/nyarlathotep.yml b/playbooks/nyarlathotep.yml
new file mode 100644
index 0000000..8f057b5
--- /dev/null
+++ b/playbooks/nyarlathotep.yml
@@ -0,0 +1,6 @@
+---
+- name: Install nyarlathotep server
+ hosts: nyarlathotep.th73.ovh
+ become: true
+ roles:
+ - { role: nginx, tags: ['www'] }
diff --git a/roles/borgbackup/defaults/main.yml b/roles/borgbackup/defaults/main.yml
new file mode 100644
index 0000000..b322028
--- /dev/null
+++ b/roles/borgbackup/defaults/main.yml
@@ -0,0 +1,8 @@
+---
+
+borg_user: "borg"
+borg_group: "borg"
+borg_dir: "/srv/borgbackup"
+borg_shell: "/bin/bash"
+borg_pool: "{{ borg_dir }}/repos"
+borg_auth_users: []
diff --git a/roles/borgbackup/tasks/main.yml b/roles/borgbackup/tasks/main.yml
new file mode 100644
index 0000000..085b99f
--- /dev/null
+++ b/roles/borgbackup/tasks/main.yml
@@ -0,0 +1,70 @@
+---
+
+- name: Ensure borgbackup is installed
+ package:
+ name: borgbackup
+ state: present
+
+- name: Add borg group
+ group:
+ name: "{{ borg_group }}"
+ state: present
+
+- name: Add borg user
+ user:
+ name: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ home: "{{ borg_dir }}"
+ shell: "{{ borg_shell }}"
+ groups: []
+ state: present
+
+- name: Ensure borg user's home directory is present
+ file:
+ path: "{{ borg_dir }}"
+ owner: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ mode: 0700
+ state: directory
+
+- name: Ensure .ssh directory exists
+ file:
+ path: "{{ borg_dir }}/.ssh"
+ owner: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ mode: 0700
+ state: directory
+
+- name: Ensure pool exists
+ file:
+ path: "{{ borg_pool }}"
+ owner: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ mode: 0700
+ state: directory
+
+# Be aware this does not remove other keys as authorized_key is broken when used
+# in exclusive mode with with_items
+- name: Setup authorized_keys
+ authorized_key:
+ user: "{{ borg_user }}"
+ key: "{{ item.key }}"
+ key_options: 'command="cd {{ borg_pool }}/{{ item.host }};borg serve --restrict-to-path {{ borg_pool }}/{{ item.host }}",restrict'
+ with_items: "{{ borg_auth_users }}"
+
+- name: Ensure .ssh/authorized_keys exists
+ file:
+ path: "{{ borg_dir }}/.ssh/authorized_keys"
+ owner: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ mode: 0600
+ state: file
+
+- name: Ensure all the user pools exist
+ file:
+ path: "{{ borg_pool }}/{{ item.host }}"
+ owner: "{{ borg_user }}"
+ group: "{{ borg_group }}"
+ mode: 0700
+ state: directory
+ with_items: "{{ borg_auth_users }}"
diff --git a/roles/dotfiles/tasks/main.yml b/roles/dotfiles/tasks/main.yml
new file mode 100644
index 0000000..f008142
--- /dev/null
+++ b/roles/dotfiles/tasks/main.yml
@@ -0,0 +1,30 @@
+---
+
+- name: Install packages
+ package: name={{ item }} state=present
+ with_items:
+ - git
+ - vim
+ - zsh
+ - htop
+ - tmux
+ become: true
+
+- name: Clone dotfiles
+ git:
+ repo: 'https://github.com/Tharre/dotfiles.git'
+ dest: "{{ ansible_user_dir }}/dotfiles"
+ recursive: no
+ register: dotfiles
+
+- name: Install dotfiles
+ shell: ./install.sh
+ args:
+ chdir: "{{ ansible_user_dir }}/dotfiles"
+ when: dotfiles.changed
+
+- name: Change shell to zsh
+ user:
+ name: "{{ ansible_user_id }}"
+ shell: /usr/bin/zsh
+ become: true
diff --git a/roles/enable-standard-cronjobs b/roles/enable-standard-cronjobs
new file mode 160000
+Subproject cf24b4c54045b9be529305c22ae35ac2af80a6f
diff --git a/roles/gitolite/defaults/main.yml b/roles/gitolite/defaults/main.yml
new file mode 100644
index 0000000..24facc6
--- /dev/null
+++ b/roles/gitolite/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+git_user: "git"
+git_group: "git"
+git_dir: "/srv/git"
+git_admin_key: "~/.ssh/id_rsa.pub"
+git_umask: "0027"
+git_config_keys: ""
diff --git a/roles/gitolite/tasks/init.yml b/roles/gitolite/tasks/init.yml
new file mode 100644
index 0000000..f745a85
--- /dev/null
+++ b/roles/gitolite/tasks/init.yml
@@ -0,0 +1,18 @@
+---
+- name: Copy admin key
+ copy:
+ src: "{{ git_admin_key }}"
+ dest: "{{ git_dir }}/admin.pub"
+ mode: 0600
+ owner: "{{ git_user }}"
+ group: "{{ git_group }}"
+
+- name: Ensure sudo is available for become_user
+ package:
+ name: sudo
+ state: present
+
+- name: Configure gitolite
+ command: gitolite setup -pk "{{ git_dir }}/admin.pub"
+ become: yes
+ become_user: "{{ git_user }}"
diff --git a/roles/gitolite/tasks/main.yml b/roles/gitolite/tasks/main.yml
new file mode 100644
index 0000000..fc05006
--- /dev/null
+++ b/roles/gitolite/tasks/main.yml
@@ -0,0 +1,40 @@
+---
+- name: Add git user
+ user:
+ name: "{{ git_user }}"
+ home: "{{ git_dir }}"
+ system: yes
+ generate_ssh_key: yes
+ state: present
+
+- name: Install gitolite (and git)
+ package:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - git-core
+ - gitolite3
+
+- name: Check if this is a new installation
+ stat:
+ path: "{{ git_dir }}/.gitolite"
+ register: gitolite_dir
+
+- include: "init.yml"
+ when: not gitolite_dir.stat.exists
+
+- name: Copy configuration from template
+ template:
+ src: gitolite.rc.j2
+ dest: "{{ git_dir }}/.gitolite.rc"
+ mode: 0644
+ owner: "{{ git_user }}"
+ group: "{{ git_group }}"
+ backup: yes
+
+- name: Set permissions on {{ git_dir }}
+ file:
+ path: "{{ git_dir }}"
+ recurse: yes
+ owner: "{{ git_user }}"
+ group: "{{ git_group }}"
diff --git a/roles/gitolite/templates/gitolite.rc.j2 b/roles/gitolite/templates/gitolite.rc.j2
new file mode 100644
index 0000000..9695d2f
--- /dev/null
+++ b/roles/gitolite/templates/gitolite.rc.j2
@@ -0,0 +1,196 @@
+# {{ ansible_managed|comment }}
+# configuration variables for gitolite
+
+# This file is in perl syntax. But you do NOT need to know perl to edit it --
+# just mind the commas, use single quotes unless you know what you're doing,
+# and make sure the brackets and braces stay matched up!
+
+# (Tip: perl allows a comma after the last item in a list also!)
+
+# HELP for commands can be had by running the command with "-h".
+
+# HELP for all the other FEATURES can be found in the documentation (look for
+# "list of non-core programs shipped with gitolite" in the master index) or
+# directly in the corresponding source file.
+
+%RC = (
+
+ # ------------------------------------------------------------------
+
+ # default umask gives you perms of '0700'; see the rc file docs for
+ # how/why you might change this
+ UMASK => {{ git_umask }},
+
+ # look for "git-config" in the documentation
+ GIT_CONFIG_KEYS => '{{ git_config_keys }}',
+
+ # comment out if you don't need all the extra detail in the logfile
+ LOG_EXTRA => 1,
+ # syslog options
+ # 1. leave this section as is for normal gitolite logging
+ # 2. uncomment this line to log only to syslog:
+ # LOG_DEST => 'syslog',
+ # 3. uncomment this line to log to syslog and the normal gitolite log:
+ # LOG_DEST => 'syslog,normal',
+
+ # roles. add more roles (like MANAGER, TESTER, ...) here.
+ # WARNING: if you make changes to this hash, you MUST run 'gitolite
+ # compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
+ ROLES => {
+ READERS => 1,
+ WRITERS => 1,
+ },
+
+ # enable caching (currently only Redis). PLEASE RTFM BEFORE USING!!!
+ # CACHE => 'Redis',
+
+ # ------------------------------------------------------------------
+
+ # rc variables used by various features
+
+ # the 'info' command prints this as additional info, if it is set
+ # SITE_INFO => 'Please see http://blahblah/gitolite for more help',
+
+ # the CpuTime feature uses these
+ # display user, system, and elapsed times to user after each git operation
+ # DISPLAY_CPU_TIME => 1,
+ # display a warning if total CPU times (u, s, cu, cs) crosses this limit
+ # CPU_TIME_WARN_LIMIT => 0.1,
+
+ # the Mirroring feature needs this
+ # HOSTNAME => "foo",
+
+ # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING!
+ # CACHE_TTL => 600,
+
+ # ------------------------------------------------------------------
+
+ # suggested locations for site-local gitolite code (see cust.html)
+
+ # this one is managed directly on the server
+ # LOCAL_CODE => "$ENV{HOME}/local",
+
+ # or you can use this, which lets you put everything in a subdirectory
+ # called "local" in your gitolite-admin repo. For a SECURITY WARNING
+ # on this, see http://gitolite.com/gitolite/cust.html#pushcode
+ # LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local",
+
+ # ------------------------------------------------------------------
+
+ # List of commands and features to enable
+
+ ENABLE => [
+
+ # COMMANDS
+
+ # These are the commands enabled by default
+ 'help',
+ 'desc',
+ 'info',
+ 'perms',
+ 'writable',
+
+ # Uncomment or add new commands here.
+ # 'create',
+ # 'fork',
+ # 'mirror',
+ # 'readme',
+ # 'sskm',
+ # 'D',
+
+ # These FEATURES are enabled by default.
+
+ # essential (unless you're using smart-http mode)
+ 'ssh-authkeys',
+
+ # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
+ 'git-config',
+
+ # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
+ 'daemon',
+
+ # creates projects.list file; if you don't use gitweb, comment this out
+ 'gitweb',
+
+ # These FEATURES are disabled by default; uncomment to enable. If you
+ # need to add new ones, ask on the mailing list :-)
+
+ # user-visible behaviour
+
+ # prevent wild repos auto-create on fetch/clone
+ # 'no-create-on-read',
+ # no auto-create at all (don't forget to enable the 'create' command!)
+ # 'no-auto-create',
+
+ # access a repo by another (possibly legacy) name
+ # 'Alias',
+
+ # give some users direct shell access. See documentation in
+ # sts.html for details on the following two choices.
+ # "Shell $ENV{HOME}/.gitolite.shell-users",
+ # 'Shell alice bob',
+
+ # set default roles from lines like 'option default.roles-1 = ...', etc.
+ # 'set-default-roles',
+
+ # show more detailed messages on deny
+ # 'expand-deny-messages',
+
+ # show a message of the day
+ # 'Motd',
+
+ # system admin stuff
+
+ # enable mirroring (don't forget to set the HOSTNAME too!)
+ # 'Mirroring',
+
+ # allow people to submit pub files with more than one key in them
+ # 'ssh-authkeys-split',
+
+ # selective read control hack
+ # 'partial-copy',
+
+ # manage local, gitolite-controlled, copies of read-only upstream repos
+ # 'upstream',
+
+ # updates 'description' file instead of 'gitweb.description' config item
+ # 'cgit',
+
+ # allow repo-specific hooks to be added
+ # 'repo-specific-hooks',
+
+ # performance, logging, monitoring...
+
+ # be nice
+ # 'renice 10',
+
+ # log CPU times (user, system, cumulative user, cumulative system)
+ # 'CpuTime',
+
+ # syntactic_sugar for gitolite.conf and included files
+
+ # allow backslash-escaped continuation lines in gitolite.conf
+ # 'continuation-lines',
+
+ # create implicit user groups from directory names in keydir/
+ # 'keysubdirs-as-groups',
+
+ # allow simple line-oriented macros
+ # 'macros',
+
+ # Kindergarten mode
+
+ # disallow various things that sensible people shouldn't be doing anyway
+ # 'Kindergarten',
+ ],
+
+);
+
+# ------------------------------------------------------------------------------
+# per perl rules, this should be the last line in such a file:
+1;
+
+# Local variables:
+# mode: perl
+# End:
+# vim: set syn=perl:
diff --git a/roles/nginx/defaults/main.yml b/roles/nginx/defaults/main.yml
new file mode 100644
index 0000000..00cd5b8
--- /dev/null
+++ b/roles/nginx/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+letsencrypt_validation_dir: "/var/lib/letsencrypt"
diff --git a/roles/nginx/files/certbot-renewal.service b/roles/nginx/files/certbot-renewal.service
new file mode 100644
index 0000000..0439b2a
--- /dev/null
+++ b/roles/nginx/files/certbot-renewal.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Let's Encrypt renewal
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/certbot renew
+ExecStartPost=/bin/systemctl reload nginx.service
diff --git a/roles/nginx/files/certbot-renewal.timer b/roles/nginx/files/certbot-renewal.timer
new file mode 100644
index 0000000..94c8b8b
--- /dev/null
+++ b/roles/nginx/files/certbot-renewal.timer
@@ -0,0 +1,10 @@
+[Unit]
+Description=Twice daily renewal of Let's Encrypt's certificates
+
+[Timer]
+OnCalendar=0/12:00:00
+RandomizedDelaySec=1h
+Persistent=true
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml
new file mode 100644
index 0000000..03a91e1
--- /dev/null
+++ b/roles/nginx/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+
+- name: restart nginx
+ service: name=nginx state=restarted
+
+- name: reload nginx
+ service: name=nginx state=reloaded
+
+- name: daemon reload
+ command: systemctl daemon-reload
diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml
new file mode 100644
index 0000000..7d8024b
--- /dev/null
+++ b/roles/nginx/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+
+- name: Install nginx
+ package:
+ name: nginx, certbot
+ state: present
+
+- name: Configure nginx
+ template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=0644
+ notify:
+ - restart nginx
+
+- name: Create snippets directory
+ file: state=directory path=/etc/nginx/snippets owner=root group=root mode=0755
+
+- name: Copy snippets
+ template: src={{ item }} dest=/etc/nginx/snippets owner=root group=root mode=0644
+ with_items:
+ - letsencrypt.conf
+ - sslsettings.conf
+ notify:
+ - reload nginx
+
+- name: Create nginx.d directory
+ file: state=directory path=/etc/nginx/nginx.d owner=root group=root mode=0755
+
+- name: Install letsencrypt renewal service
+ copy: src={{ item }} dest=/etc/systemd/system/{{ item }} owner=root group=root mode=0644
+ with_items:
+ - certbot-renewal.service
+ - certbot-renewal.timer
+ notify:
+ - daemon reload
+
+- name: Enable nginx
+ service: name=nginx enabled=yes
diff --git a/roles/nginx/templates/letsencrypt.conf b/roles/nginx/templates/letsencrypt.conf
new file mode 100644
index 0000000..99dd6c6
--- /dev/null
+++ b/roles/nginx/templates/letsencrypt.conf
@@ -0,0 +1,5 @@
+location /.well-known/acme-challenge {
+ root {{ letsencrypt_validation_dir }};
+ default_type "text/plain";
+ try_files $uri =404;
+}
diff --git a/roles/nginx/templates/nginx.conf.j2 b/roles/nginx/templates/nginx.conf.j2
new file mode 100644
index 0000000..00b2789
--- /dev/null
+++ b/roles/nginx/templates/nginx.conf.j2
@@ -0,0 +1,29 @@
+user http;
+worker_processes auto;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ log_format main '$remote_addr $host $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for" $request_time';
+
+ sendfile on;
+ keepalive_timeout 65;
+ client_max_body_size 16M;
+
+ gzip on;
+ gzip_comp_level 6;
+ gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
+
+ index index.php index.html index.htm;
+
+ include snippets/sslsettings.conf;
+
+ include nginx.d/*.conf;
+}
diff --git a/roles/nginx/templates/sslsettings.conf b/roles/nginx/templates/sslsettings.conf
new file mode 100644
index 0000000..761c554
--- /dev/null
+++ b/roles/nginx/templates/sslsettings.conf
@@ -0,0 +1,18 @@
+ssl_session_timeout 1d;
+ssl_session_cache shared:SSL:50m;
+ssl_session_tickets off;
+
+ssl_protocols TLSv1.2;
+ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
+ssl_prefer_server_ciphers on;
+
+# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
+add_header Strict-Transport-Security max-age=15768000;
+
+# OCSP Stapling ---
+# fetch OCSP records from URL in ssl_certificate and cache them
+ssl_stapling on;
+ssl_stapling_verify on;
+
+resolver 8.8.8.8 8.8.4.4 valid=300s;
+resolver_timeout 5s;
diff --git a/roles/postfix b/roles/postfix
new file mode 160000
+Subproject 0841cbfadd164d72f95f3fcdb6c86212d0e9a13
diff --git a/roles/teamspeak b/roles/teamspeak
new file mode 160000
+Subproject 3364b73e2f48cc47a4aa6c24e088d05269b453c
diff --git a/roles/unattended-upgrades b/roles/unattended-upgrades
new file mode 160000
+Subproject 989c54701854d439f232869526c0e93719e0389