diff --git a/roles/archmanweb/defaults/main.yml b/roles/archmanweb/defaults/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..7f3e0e2814d49cbed975faab31c5a15ec9872942 --- /dev/null +++ b/roles/archmanweb/defaults/main.yml @@ -0,0 +1,15 @@ +--- +archmanweb_dir: '/srv/http/archmanweb' +archmanweb_cache_dir: '{{ archmanweb_dir }}/cache' +archmanweb_domain: 'man.archlinux.org' +archmanweb_allowed_hosts: ["{{ archmanweb_domain }}"] +archmanweb_nginx_conf: '/etc/nginx/nginx.d/archmanweb.conf' +archmanweb_repository: 'https://github.com/lahwaacz/archmanweb.git' +archmanweb_version: deployment +archmanweb_django_settings_module: production.settings +#archmanweb_pgp_key: ['932BA3FA0C86812A32D1F54DAB5964AEB9FEDDDC'] # Jakub Klinkovský (lahwaacz) +archmanweb_forced_deploy: false + +archmanweb_db: 'archmanweb' +archmanweb_db_host: 'localhost' +archmanweb_db_user: 'archmanweb' diff --git a/roles/archmanweb/tasks/main.yml b/roles/archmanweb/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..9d4029e89ccce2bd91d11f05049a579d1e011129 --- /dev/null +++ b/roles/archmanweb/tasks/main.yml @@ -0,0 +1,89 @@ +--- + +- name: install required packages + pacman: + state: present + name: + - git + - mandoc + - pyalpm + - python-chardet + - python-django + - python-psycopg2 + - python-requests + - python-xtarfile + - uwsgi-plugin-python + +- name: make archmanweb user + user: name=archmanweb shell=/bin/false home="{{ archmanweb_dir }}" + +- name: fix home permissions + file: state=directory owner=archmanweb group=archmanweb mode=0755 path="{{ archmanweb_dir }}" + +- name: set archmanweb groups + user: name=archmanweb groups=uwsgi + +- name: set up nginx + template: src=nginx.d.conf.j2 dest="{{ archmanweb_nginx_conf }}" owner=root group=root mode=644 + notify: reload nginx + tags: ['nginx'] + +- name: make nginx log dir + file: path=/var/log/nginx/{{ archmanweb_domain }} state=directory owner=root group=root mode=0755 + +- name: clone archmanweb repo + git: > + repo={{ archmanweb_repository }} + dest="{{ archmanweb_dir }}/repo" + version={{ archmanweb_version }} +# TODO +# verify_commit=true +# gpg_whitelist={{ archmanweb_pgp_key }} + become: true + become_user: archmanweb + register: release + +- name: configure archmanweb + template: src=local_settings.py.j2 dest={{ archmanweb_dir }}/repo/production/local_settings.py owner=archmanweb group=archmanweb mode=0660 + register: config + no_log: true + +- name: create archmanweb db user + postgresql_user: name={{ archmanweb_db_user }} password={{ vault_archmanweb_db_password }} login_host="{{ archmanweb_db_host }}" login_password="{{ vault_postgres_users.postgres }}" encrypted=yes + no_log: true + +- name: create archmanweb db + postgresql_db: name="{{ archmanweb_db }}" login_host="{{ archmanweb_db_host }}" login_password="{{ vault_postgres_users.postgres }}" owner="{{ archmanweb_db_user }}" + register: db_created + +- name: add pg_trgm extension to the archmanweb db + postgresql_ext: name="pg_trgm" db="{{ archmanweb_db }}" login_host="{{ archmanweb_db_host }}" login_password="{{ vault_postgres_users.postgres }}" + when: db_created.changed or archmanweb_forced_deploy + +- name: run Django management tasks + django_manage: app_path="{{ archmanweb_dir }}/repo" command="{{ item }}" + with_items: + - migrate + - collectstatic + - man_drop_cache + environment: + DJANGO_SETTINGS_MODULE: "{{ archmanweb_django_settings_module }}" + become: true + become_user: archmanweb + when: db_created.changed or release.changed or config.changed or archmanweb_forced_deploy + +- name: configure UWSGI for archmanweb + template: src=archmanweb.ini.j2 dest=/etc/uwsgi/vassals/archmanweb.ini owner=archmanweb group=http mode=0640 + +- name: deploy new release + file: path=/etc/uwsgi/vassals/archmanweb.ini state=touch owner=archmanweb group=http mode=0640 + when: release.changed or config.changed or archmanweb_forced_deploy + +- name: install systemd units + template: src="{{ item }}.j2" dest="/etc/systemd/system/{{ item }}" owner=root group=root mode=0644 + with_items: + - archmanweb_update.service + - archmanweb_update.timer + +- name: start and enable archmanweb update timer + systemd: name="archmanweb_update.timer" enabled=yes state=started daemon_reload=yes diff --git a/roles/archmanweb/templates/archmanweb.ini.j2 b/roles/archmanweb/templates/archmanweb.ini.j2 new file mode 100644 index 0000000000000000000000000000000000000000..29e95a3adae16a15d448e394f245c1dc8f27b79f --- /dev/null +++ b/roles/archmanweb/templates/archmanweb.ini.j2 @@ -0,0 +1,15 @@ +[uwsgi] +plugins = python +chdir = {{ archmanweb_dir }}/repo +env = DJANGO_SETTINGS_MODULE={{ archmanweb_django_settings_module }} +module = wsgi:application +socket = /run/uwsgi/archmanweb.sock +chmod-socket = 660 +processes = 4 +threads = 1 +master = true +uid = archmanweb +gid = http +thunder-lock = true +daemonize = /var/log/uwsgi/archmanweb.log +stats = /run/uwsgi/archmanweb-stats.sock diff --git a/roles/archmanweb/templates/archmanweb_update.service.j2 b/roles/archmanweb/templates/archmanweb_update.service.j2 new file mode 100644 index 0000000000000000000000000000000000000000..94ff1b921662a2970be91013ed5c5f91f1001d52 --- /dev/null +++ b/roles/archmanweb/templates/archmanweb_update.service.j2 @@ -0,0 +1,23 @@ +[Unit] +Description=Update archmanweb database + +[Service] +Type=oneshot +User=archmanweb +WorkingDirectory={{ archmanweb_dir }}/repo/ +Environment=DJANGO_SETTINGS_MODULE="{{ archmanweb_django_settings_module }}" +ExecStart=/usr/bin/python3 manage.py man_update --cache-dir {{ archmanweb_cache_dir }} + +ProtectSystem=full +PrivateTmp=true +PrivateDevices=true + +ProtectHostname=true +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectKernelLogs=true +ProtectControlGroups=true + +NoNewPrivileges=true +RestrictRealtime=true +MemoryDenyWriteExecute=true diff --git a/roles/archmanweb/templates/archmanweb_update.timer.j2 b/roles/archmanweb/templates/archmanweb_update.timer.j2 new file mode 100644 index 0000000000000000000000000000000000000000..3aa8001300893bd98f89730ecedd52ffba1fff18 --- /dev/null +++ b/roles/archmanweb/templates/archmanweb_update.timer.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=Timer for the archmanweb update + +[Timer] +OnCalendar=daily +Persistent=true +RandomizedDelaySec=1h + +[Install] +WantedBy=timers.target diff --git a/roles/archmanweb/templates/local_settings.py.j2 b/roles/archmanweb/templates/local_settings.py.j2 new file mode 100644 index 0000000000000000000000000000000000000000..2513be3f9bd4ac30d9911e03b83b487d0584b9b3 --- /dev/null +++ b/roles/archmanweb/templates/local_settings.py.j2 @@ -0,0 +1,26 @@ +DEBUG = False + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '{{ vault_archmanweb_secret_key }}' + +# Hostnames we allow this site to be served under +ALLOWED_HOSTS = [{% for host in archmanweb_allowed_hosts %}'{{ host }}', {% endfor -%}] + +DATABASES = { + 'default': { + 'ENGINE' : 'django.db.backends.postgresql_psycopg2', + 'PORT' : 5432, +{% if archmanweb_db_host != 'localhost' %} + 'HOST' : '{{ archmanweb_db_host }}', +{% endif %} + 'NAME' : '{{ archmanweb_db }}', + 'USER' : '{{ archmanweb_db_user }}', + 'PASSWORD': '{{ vault_archmanweb_db_password }}', + 'OPTIONS' : { + 'application_name': 'archmanweb', +{% if archmanweb_db_host != 'localhost' %} + 'sslmode': 'require', +{% endif %} + } + }, +} diff --git a/roles/archmanweb/templates/nginx.d.conf.j2 b/roles/archmanweb/templates/nginx.d.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..f373771e6fa039474422518bae982b83c486f911 --- /dev/null +++ b/roles/archmanweb/templates/nginx.d.conf.j2 @@ -0,0 +1,50 @@ +upstream archmanweb { + server unix:///run/uwsgi/archmanweb.sock; +} + +server { + listen 80; + listen [::]:80; + server_name {{ archmanweb_domain }}; + + access_log /var/log/nginx/{{ archmanweb_domain }}/access.log reduced; + error_log /var/log/nginx/{{ archmanweb_domain }}/error.log; + + include snippets/letsencrypt.conf; + + location / { + access_log off; + return 301 https://$server_name$request_uri; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ archmanweb_domain }}; + + access_log /var/log/nginx/{{ archmanweb_domain }}/access.log reduced; + error_log /var/log/nginx/{{ archmanweb_domain }}/error.log; + + ssl_certificate /etc/letsencrypt/live/{{ archmanweb_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ archmanweb_domain }}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{{ archmanweb_domain }}/chain.pem; + + location /favicon.ico { + alias {{ archmanweb_dir }}/repo/collected_static/favicon.ico; + } + + # Client-cache for Django's static assets + location /static { + expires 30d; + add_header Pragma public; + add_header Cache-Control "public"; + alias {{ archmanweb_dir }}/repo/collected_static; + } + + location / { + access_log /var/log/nginx/{{ archmanweb_domain }}/access.log main; + include uwsgi_params; + uwsgi_pass archmanweb; + } +}