diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b36779c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vault_pass diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml index a6819d8..4285a1a 100644 --- a/group_vars/all/vars.yml +++ b/group_vars/all/vars.yml @@ -1,7 +1,14 @@ --- +certmgr_mode: webserver + ntp_servers: - 0.de.pool.ntp.org - 1.de.pool.ntp.org - 2.de.pool.ntp.org - 3.de.pool.ntp.org + +confluence_domain: confluence.regensburg.freifunk.net +confluence_dbname: confluence +confluence_dbuser: confluence +confluence_dbpass: "{{ vault_confluence_dbpass }}" diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml new file mode 100644 index 0000000..d4a90a1 --- /dev/null +++ b/group_vars/all/vault.yml @@ -0,0 +1,8 @@ +$ANSIBLE_VAULT;1.1;AES256 +38393463366165376337303430613766323835326132323439633630643737626439346536333766 +6532613835646564643634343536613265626263333939330a613237613738613339316561616431 +35313665616333636631633964396533646233313866333465613535323438646534313434353064 +3134313234636136330a623439356663666635623464303561343733633962336439663166373966 +63663234373663393236616537633963323935313439373735646365333532643731613462633835 +30616531366636313765303464656435633734376439313261336566353739316635633731396163 +303065396363633534376166353932373539 diff --git a/roles/certmgr/tasks/main.yml b/roles/certmgr/tasks/main.yml new file mode 100644 index 0000000..a362160 --- /dev/null +++ b/roles/certmgr/tasks/main.yml @@ -0,0 +1,44 @@ +--- + +- name: Enable backports + apt_repository: repo='deb http://httpredir.debian.org/debian jessie-backports main' state=present + +- name: Install dependencies + apt: name={{ item }} state=present + with_items: + - git + - python-dateutil + - python-yaml + +- name: Install python-openssl + apt: name=python-openssl default_release=jessie-backports state=latest + +- name: Install acertmgr + git: repo=https://github.com/moepman/acertmgr.git dest=/opt/acertmgr depth=1 version=480337648699cfbe321774dee1d8aa82eb27b626 + +- name: Create config directories + file: path={{ item }} state=directory mode=0755 + with_items: + - /etc/acme + - /etc/acme/domains.d + +- name: Configure acertmgr + template: src=acme.conf.j2 dest=/etc/acme/acme.conf + +- name: Create private keys + command: openssl genrsa -out {{ item }} 4096 creates={{ item }} + with_items: + - /etc/acme/account.key + - /etc/acme/server.key + +- name: Ensure private key permissoins + file: path={{ item }} owner=root mode=0400 + with_items: + - /etc/acme/account.key + - /etc/acme/server.key + +- name: Create challenge directory + file: path=/var/www/acme-challenge/ owner=root mode=0755 state=directory + +- name: Enable acertmgr cronjob + cron: name=certmgr special_time=daily job=/opt/acertmgr/acertmgr.py diff --git a/roles/certmgr/templates/acme.conf.j2 b/roles/certmgr/templates/acme.conf.j2 new file mode 100644 index 0000000..c0488bb --- /dev/null +++ b/roles/certmgr/templates/acme.conf.j2 @@ -0,0 +1,9 @@ +--- + +mode: {{ certmgr_mode }} +webdir: /var/www/acme-challenge/ +ttl_days: 30 +authority: "https://acme-v01.api.letsencrypt.org" + +defaults: + cafile: /etc/acme/lets-encrypt-x3-cross-signed.pem diff --git a/roles/confluence/handlers/main.yml b/roles/confluence/handlers/main.yml new file mode 100644 index 0000000..44975c4 --- /dev/null +++ b/roles/confluence/handlers/main.yml @@ -0,0 +1,4 @@ +--- + +- name: Restart nginx + service: name=nginx state=restarted diff --git a/roles/confluence/meta/main.yml b/roles/confluence/meta/main.yml new file mode 100644 index 0000000..8d2c010 --- /dev/null +++ b/roles/confluence/meta/main.yml @@ -0,0 +1,5 @@ +--- + +dependencies: +- { role: certmgr } +- { role: nginx, nginx_ssl: True } diff --git a/roles/confluence/tasks/main.yml b/roles/confluence/tasks/main.yml new file mode 100644 index 0000000..b21aac4 --- /dev/null +++ b/roles/confluence/tasks/main.yml @@ -0,0 +1,35 @@ +--- + +- name: Install packages + apt: name={{ item }} state=present + with_items: + - postgresql + - python-psycopg2 + +- name: Configure PostgreSQL database + postgresql_db: name={{ confluence_dbname }} + become: true + become_user: postgres + +- name: Configure PostgreSQL user + postgresql_user: db={{ confluence_dbname }} name={{ confluence_dbuser }} password={{ confluence_dbpass }} priv=ALL state=present + become: true + become_user: postgres + +- name: Ensure certificates are available + command: openssl req -x509 -nodes -newkey rsa:2048 -keyout /etc/nginx/ssl/{{ confluence_domain }}.key -out /etc/nginx/ssl/{{ confluence_domain }}.crt -days 730 -subj "/CN={{ confluence_domain }}" creates=/etc/nginx/ssl/{{ confluence_domain }}.crt + notify: Restart nginx + +- name: Configure certificate manager for confluence + template: src=certs.j2 dest=/etc/acme/domains.d/{{ confluence_domain }}.conf + +- name: Configure vhost + template: src=vhost.j2 dest=/etc/nginx/sites-available/confluence + notify: Restart nginx + +- name: Enable vhost + file: src=/etc/nginx/sites-available/confluence dest=/etc/nginx/sites-enabled/confluence state=link + notify: Restart nginx + +- name: Start PostgreSQL + service: name=postgresql state=started enabled=yes diff --git a/roles/confluence/templates/certs.j2 b/roles/confluence/templates/certs.j2 new file mode 100644 index 0000000..27c4582 --- /dev/null +++ b/roles/confluence/templates/certs.j2 @@ -0,0 +1,15 @@ +--- + +{{ confluence_domain }}: +- path: /etc/nginx/ssl/{{ confluence_domain }}.key + user: root + group: root + perm: '400' + format: key + action: 'service nginx restart' +- path: /etc/nginx/ssl/{{ confluence_domain }}.crt + user: root + group: root + perm: '400' + format: crt,ca + action: 'service nginx restart' diff --git a/roles/confluence/templates/vhost.j2 b/roles/confluence/templates/vhost.j2 new file mode 100644 index 0000000..eba17cf --- /dev/null +++ b/roles/confluence/templates/vhost.j2 @@ -0,0 +1,32 @@ +server { + listen 80; + listen [::]:80; + + server_name {{ confluence_domain }}; + + location /.well-known/acme-challenge { + default_type "text/plain"; + alias /var/www/acme-challenge; + } + + location / { + return 301 https://{{ confluence_domain }}$request_uri; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name {{ confluence_domain }}; + + ssl_certificate_key /etc/nginx/ssl/{{ confluence_domain }}.key; + ssl_certificate /etc/nginx/ssl/{{ confluence_domain }}.crt; + + location / { + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://localhost:8090/; + } +} diff --git a/roles/nginx/files/nginx.conf b/roles/nginx/files/nginx.conf new file mode 100644 index 0000000..f93321e --- /dev/null +++ b/roles/nginx/files/nginx.conf @@ -0,0 +1,68 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_dhparam /etc/nginx/dhparam.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; + + ssl_stapling on; + ssl_stapling_verify on; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ## + # Gzip Settings + ## + + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml new file mode 100644 index 0000000..44975c4 --- /dev/null +++ b/roles/nginx/handlers/main.yml @@ -0,0 +1,4 @@ +--- + +- name: Restart nginx + service: name=nginx state=restarted diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..7862ad3 --- /dev/null +++ b/roles/nginx/tasks/main.yml @@ -0,0 +1,39 @@ +--- + +- name: Enable backports + apt_repository: repo='deb http://httpredir.debian.org/debian jessie-backports main' state=present + +- name: Install nginx + apt: name=nginx-light default_release=jessie-backports state=latest + +- name: Create certificate directory + file: path=/etc/nginx/ssl state=directory mode=0750 + when: nginx_ssl == True + +- name: Ensure certificates are available + command: openssl req -x509 -nodes -newkey rsa:2048 -keyout /etc/nginx/ssl/{{ ansible_fqdn }}.key -out /etc/nginx/ssl/{{ ansible_fqdn }}.crt -days 730 -subj "/CN={{ ansible_fqdn }}" creates=/etc/nginx/ssl/{{ ansible_fqdn }}.crt + when: nginx_ssl == True + notify: Restart nginx + +- name: Ensure correct certificate permissions + file: path=/etc/nginx/ssl/{{ ansible_fqdn }}.key owner=root mode=0400 + when: nginx_ssl == True + notify: Restart nginx + +- name: Create DH parameters + command: openssl dhparam -outform PEM -out {{ item }} 2048 creates={{ item }} + when: nginx_ssl == True + with_items: + - /etc/nginx/dhparam.pem + +- name: Configure nginx + copy: src=nginx.conf dest=/etc/nginx/nginx.conf + notify: Restart nginx + +- name: Configure default vhost + template: src=default.j2 dest=/etc/nginx/sites-available/default + when: nginx_ssl == True + notify: Restart nginx + +- name: Start nginx + service: name=nginx state=started enabled=yes diff --git a/roles/nginx/templates/default.j2 b/roles/nginx/templates/default.j2 new file mode 100644 index 0000000..4da35a5 --- /dev/null +++ b/roles/nginx/templates/default.j2 @@ -0,0 +1,26 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + server_name _; + server_name_in_redirect on; + + location /.well-known/acme-challenge { + default_type "text/plain"; + alias /var/www/acme-challenge; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name _; + + ssl_certificate_key /etc/nginx/ssl/{{ ansible_fqdn }}.key; + ssl_certificate /etc/nginx/ssl/{{ ansible_fqdn }}.crt; +} diff --git a/site.yml b/site.yml index f864781..1a3fd81 100644 --- a/site.yml +++ b/site.yml @@ -5,3 +5,8 @@ roles: - common - ntp + +- name: Setup confluence server + hosts: confluence.regensburg.freifunk.net + roles: + - confluence