--- - hosts: ponyconfs vars: ponyconf_sites: - domain: 'cfp-2023.pycon.fr' authenticator: gandi ponyconf_user: ponyconf ponyconf_home: "/home/{{ ponyconf_user }}" ponyconf_imap_password: !vault | $ANSIBLE_VAULT;1.1;AES256 66393662376362313833356630353764323934666561316337356531663761343239373663643137 3939306166383561396136303637653961613830636639310a396237393764396566313436663062 35326135326334613363353633623034613063326239663232663033646335363930333763326131 3731396233613339330a663330616134633937366136613932393361363434616433663765373063 30353439616663633734656230353736656633653532373665653237656263376536 ponyconf_secret: !vault | $ANSIBLE_VAULT;1.1;AES256 32626263653065663534326530636136303864343934346538323232356133616263383432333566 3166653266366566626362623864343464323934623166640a663838303764316131373938663432 30623833376433383766636362306361363137383639643130306536623135353362326539343164 3633303531643964390a616464376137613634663334646230343365343938633462643737376637 30383361643563373130393737616430316363363836333632393565616332666336643766613937 30386264356266373033383436383462333038656133363530313161646632353366393631393036 363439633164376438376431373935643634 tasks: - name: Basic setup include_role: name=common - name: Install dependencies apt: state: present name: - gettext - name: Ponyconf user user: name: "{{ ponyconf_user }}" home: "{{ ponyconf_home }}" system: true - name: cfp-2024 is now a pretalx instance include_role: name=nginx vars: nginx_domain: "cfp-2024.pycon.fr" nginx_certificates: ["cfp-2024.pycon.fr"] nginx_conf: | server { listen [::]:80; listen 80; server_name cfp-2024.pycon.fr; return 301 https://$host$request_uri; } server { listen [::]:443 ssl http2; listen 443 ssl http2; server_name cfp-2024.pycon.fr; include snippets/letsencrypt-cfp-2024.pycon.fr.conf; return 301 https://cfp.pycon.fr$request_uri; } - name: PonyConf nginx config include_role: name=nginx loop: "{{ ponyconf_sites }}" vars: certbot_authenticator: "{{ item.authenticator }}" nginx_domain: "{{ item.domain }}" nginx_certificates: ["{{ item.domain }}"] nginx_conf: | server { listen [::]:80; listen 80; server_name {{ item.domain }}; return 301 https://{{ item.domain }}$request_uri; } server { listen [::]:443 ssl http2; listen 443 ssl http2; server_name {{ item.domain }}; include snippets/letsencrypt-{{ item.domain }}.conf; location /static/ { alias {{ ponyconf_home }}/static/; } location / { proxy_pass http://unix:{{ ponyconf_home }}/ponyconf.sock; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; } } - name: Clone PonyConf become: true become_user: "{{ ponyconf_user }}" git: repo: https://git.afpy.org/AFPy/PonyConf dest: "{{ ponyconf_home }}/src/" notify: restart ponyconf - name: Setup or upgrade venv become: true become_user: "{{ ponyconf_user }}" command: python3 -m venv --upgrade-deps "{{ ponyconf_home }}/venv/" changed_when: False - name: Setup PonyConf venv become: true become_user: "{{ ponyconf_user }}" pip: requirements: "{{ ponyconf_home }}/src/requirements.txt" virtualenv_command: /usr/bin/python3 -m venv virtualenv: "{{ ponyconf_home }}/venv/" - name: Install gunicorn become: true become_user: "{{ ponyconf_user }}" pip: name: gunicorn virtualenv_command: /usr/bin/python3 -m venv virtualenv: "{{ ponyconf_home }}/venv/" - name: PonyConf config copy: dest: "{{ ponyconf_home }}/src/afpy_settings.py" owner: "{{ ponyconf_user }}" group: "{{ ponyconf_user }}" mode: 0600 content: | from ponyconf.settings import * SECRET_KEY = "{{ ponyconf_secret }}" ALLOWED_HOSTS = {{ ponyconf_sites | map(attribute='domain') | to_json }} SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') DEBUG = False LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "django.server": { "()": "django.utils.log.ServerFormatter", "format": "[{server_time}] {message}", "style": "{", } }, "handlers": { "mail_admins": { "class": "django.utils.log.AdminEmailHandler", "level": "ERROR", # But the emails are plain text by default - HTML is nicer "include_html": True, }, "console": { "level": "INFO", "class": "logging.StreamHandler", "formatter": "django.server", }, "django.server": { "level": "INFO", "class": "logging.StreamHandler", "formatter": "django.server", }, }, "loggers": { "": {"handlers": ["console"], "level": "INFO"}, "django": { "handlers": ["console", "mail_admins"], "level": "INFO", "propagate": True, }, }, } STATIC_ROOT = '{{ ponyconf_home }}/static' STATIC_URL = '/static/' MEDIA_ROOT = '{{ ponyconf_home }}/media' MEDIA_URL = '/media/' DEFAULT_FROM_EMAIL = 'noreply@afpy.org' SERVER_EMAIL = 'ponyconf@afpy.org' EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = '127.0.0.1' EMAIL_SUBJECT_PREFIX = "[PonyConf] " EMAIL_PORT = 25 ADMINS = ( ('PonyConf Admins', 'julien@afpy.org'), ) TIME_ZONE = 'Europe/Paris' LANGUAGE_CODE = 'fr-FR' SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') USE_X_FORWARDED_HOST = True del SITE_ID CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'cache', } } SELECT2_CACHE_BACKEND = 'default' - name: Migrate db command: "{{ ponyconf_home }}/venv/bin/python manage.py migrate" args: chdir: "{{ ponyconf_home }}/src" environment: DJANGO_SETTINGS_MODULE: afpy_settings register: migrate_result changed_when: '" Applying " in migrate_result.stdout' run_once: true become: true become_user: "{{ ponyconf_user }}" - name: Create sites command: "{{ ponyconf_home }}/venv/bin/python manage.py addsite {{ item.domain|quote }}" loop: "{{ ponyconf_sites }}" register: create_site changed_when: '"Created" in create_site.stdout' args: chdir: "{{ ponyconf_home }}/src" environment: DJANGO_SETTINGS_MODULE: afpy_settings - name: Collectstatic command: "{{ ponyconf_home }}/venv/bin/python manage.py collectstatic --noinput" args: chdir: "{{ ponyconf_home }}/src" environment: DJANGO_SETTINGS_MODULE: afpy_settings register: collectstatic_result changed_when: '"Copying " in collectstatic_result.stdout' - name: Compile gettext command: "{{ ponyconf_home }}/venv/bin/python manage.py compilemessages" args: chdir: "{{ ponyconf_home }}/src" notify: restart ponyconf - name: Create Cache Table command: "{{ ponyconf_home }}/venv/bin/python manage.py createcachetable" args: chdir: "{{ ponyconf_home }}/src" environment: DJANGO_SETTINGS_MODULE: afpy_settings - name: "PonyConf service" notify: restart ponyconf copy: dest: /etc/systemd/system/ponyconf.service content: | [Unit] Description=PonyConf After=network.target [Service] Type=simple Environment="DJANGO_SETTINGS_MODULE=afpy_settings" ExecStart={{ ponyconf_home }}/venv/bin/gunicorn --pid {{ ponyconf_home }}/ponyconf.pid \ --bind unix:{{ ponyconf_home }}/ponyconf.sock -w 2 ponyconf.wsgi User={{ ponyconf_user }} Group={{ ponyconf_user }} WorkingDirectory={{ ponyconf_home }}/src/ Restart=on-failure [Install] WantedBy=multi-user.target - name: Start PonyConf service: name=ponyconf enabled=yes state=started daemon_reload=yes - name: Ponyconf fetchmail cron cron: user: "{{ ponyconf_user }}" name: fetchmail minute: "*/5" job: "cd /home/ponyconf/src; /home/ponyconf/venv/bin/python manage.py fetchmail --host mail.gandi.net --user cfp@pycon.fr --password {{ ponyconf_imap_password }} --settings afpy_settings" handlers: - name: restart ponyconf systemd: daemon_reload: true state: restarted name: ponyconf