--- - hosts: webservers vars: nginx_public_deploy_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINbgxOufHY7SxQrJNTlHmye+xeNHBA1O5SGtGhGeOVZM" tasks: - name: Basic setup include_role: name=common - name: Configure french locale locale_gen: name="{{ item }}" state=present with_items: - en_US.UTF-8 - fr_FR.UTF-8 - name: Install requirements apt: state: present name: [nginx, python3-passlib, sudo] # passlib to generate htpasswd - name: Generate AFPy admin htpasswd htpasswd: path: "/etc/nginx/afpy.org.htpasswd" name: "{{ item.username }}" password: "{{ item.password }}" owner: root group: www-data mode: 0640 loop: "{{ afpy_org_admins }}" loop_control: label: "{{ item.username }}" notify: reload nginx - name: Setup afpy.org include_role: name=julienpalard.nginx vars: nginx_owner: afpy-org nginx_domain: afpy.org nginx_certificates: [afpy.org, www.afpy.org] nginx_conf: | server { listen 80; server_name www.afpy.org afpy.org; access_log /var/log/nginx/afpy.org-access.log; error_log /var/log/nginx/afpy.org-error.log; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name www.afpy.org afpy.org; access_log /var/log/nginx/afpy.org-access.log; error_log /var/log/nginx/afpy.org-error.log; root /var/www/afpy.org/; include snippets/letsencrypt-afpy.org.conf; index index.html; location / { include proxy_params; proxy_pass http://unix:/run/afpy-org/website.sock; } location /static/ { alias /home/afpy-org/src/static/; } location /admin/ { auth_basic "Administration"; auth_basic_user_file afpy.org.htpasswd; include proxy_params; proxy_pass http://unix:/run/afpy-org/website.sock; } location ~ ^/doc/python/(.*)$ {return 301 https://docs.python.org/fr/$1;} location = /logo.png { return 301 https://www.afpy.org/static/images/logo.svg; } location = /offres-demploi/RSS { return 301 https://www.afpy.org/feed/emplois/rss.xml; } location = "/news/aggregator" { return 301 https://www.afpy.org/posts/actualites/1345367761; } location = "/news/pyconfr-2012" { return 301 https://www.afpy.org/posts/actualites/1345377295; } location = "/news/le-nouveau-site-de-lafpy" { return 301 https://www.afpy.org/posts/actualites/1364754937; } location = "/news/un-hackathon-a-paris" { return 301 https://www.afpy.org/posts/actualites/1373474773; } location = "/news/julython-contribuez-a-des-projets-opensource" { return 301 https://www.afpy.org/posts/actualites/1373475142; } location = "/news/lappel-a-contribution-pour-pyconfr13-est-ouvert" { return 301 https://www.afpy.org/posts/actualites/1374511126; } location = "/news/naissance-dune-communaute-saltstack-francophone" { return 301 https://www.afpy.org/posts/actualites/1392304489; } location = "/news/pycon-fr-2014" { return 301 https://www.afpy.org/posts/actualites/1392311614; } location = "/news/pyconfr15-ou-nous-emmeneras-tu-cette-annee" { return 301 https://www.afpy.org/posts/actualites/1423208987; } location = "/news/pycon-fr-2015-we-want-you" { return 301 https://www.afpy.org/posts/actualites/1433966273; } location = "/news/pycon-fr-2015-lappel-a-conferencier-est-prolonge" { return 301 https://www.afpy.org/posts/actualites/1438067732; } location = "/news/pv-de-lassemblee-generale-ordinaire-2017" { return 301 https://www.afpy.org/posts/actualites/1506345679; } location = "/news/code-en-seine" { return 301 https://www.afpy.org/posts/actualites/1507801636; } location = "/news/rencontre-python-a-lyon" { return 301 https://www.afpy.org/posts/actualites/1508335902; } location = "/news/cours-en-ligne-python-3-des-fondamentaux-aux-concepts-avances-du-langage" { return 301 https://www.afpy.org/posts/actualites/1509982321; } location = "/news/atelier-de-contribution-a-ansible-a-paris" { return 301 https://www.afpy.org/posts/actualites/1509982513; } location = "/news/rencontre-python-a-lyon-une-carte-pour-les-amener-tous-et-dans-la-connaissance-les-lier" { return 301 https://www.afpy.org/posts/actualites/1510650668; } location = "/news/hackaton-la-boite-incubateur-imt-atlantique-rennes" { return 301 https://www.afpy.org/posts/actualites/1511358816; } location = "/news/ou-sont-mes-variables" { return 301 https://www.afpy.org/posts/actualites/1512378516; } location = "/news/a-vos-framewoks" { return 301 https://www.afpy.org/posts/actualites/1512996562; } location = "/news/atelier-contribuez-a-la-traduction-de-la-doc-de-python-en-francais" { return 301 https://www.afpy.org/posts/actualites/1515405342; } location = "/news/soiree-python-a-marseille-le-9-2-2018" { return 301 https://www.afpy.org/posts/actualites/1518042512; } location = "/news/meetup-python-amiens-1" { return 301 https://www.afpy.org/posts/actualites/1523519011; } } - name: afpy user can reload own website lineinfile: path: /etc/sudoers state: present regexp: '^afpy-org ' line: "afpy-org ALL = NOPASSWD: /bin/systemctl restart afpy-org.service" validate: /usr/sbin/visudo -cf %s - name: Initial clone become: true become_user: afpy-org git: repo: https://github.com/AFPy/site/ dest: /home/afpy-org/src/ update: no - name: pip install AFPy website become: true become_user: afpy-org pip: name: /home/afpy-org/src/ virtualenv_command: /usr/bin/python3 -m venv virtualenv: "/home/afpy-org/venv/" - name: pip install gunicorn become: true become_user: afpy-org pip: name: gunicorn virtualenv_command: /usr/bin/python3 -m venv virtualenv: "/home/afpy-org/venv/" - name: systemd afpy.org service copy: dest: /etc/systemd/system/afpy-org.service content: | [Unit] Description=AFPy website After=network.target [Service] PIDFile=/run/afpy-org/website.pid User=afpy-org Group=afpy-org RuntimeDirectory=afpy-org WorkingDirectory=/home/afpy-org/src/ Environment="SENTRY_DSN={{ afpy_org_sentry_dsn }}" ExecStart=/home/afpy-org/venv/bin/gunicorn -w 4 \ --pid /run/afpy-org/website.pid \ --bind unix:/run/afpy-org/website.sock afpy:app ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target - service: name=afpy-org state=started enabled=yes - name: Redirect planet.afpy.org include_role: name=julienpalard.nginx vars: nginx_domain: planet.afpy.org nginx_certificates: [planet.afpy.org] nginx_conf: | server { listen 80; server_name planet.afpy.org; access_log /var/log/nginx/planet.afpy.org-access.log; error_log /var/log/nginx/planet.afpy.org-error.log; return 301 https://www.afpy.org/planet/; } server { listen 443 ssl; server_name planet.afpy.org; access_log /var/log/nginx/planet.afpy.org-access.log; error_log /var/log/nginx/planet.afpy.org-error.log; include snippets/letsencrypt-planet.afpy.org.conf; return 301 https://www.afpy.org/planet/; } - name: Setup salt-fr.afpy.org include_role: name=julienpalard.nginx vars: nginx_owner: salt-fr-afpy-org nginx_path: /var/www/salt-fr.afpy.org nginx_domain: salt-fr.afpy.org nginx_certificates: [salt-fr.afpy.org] nginx_public_deploy_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHVrME7+AYhM4n6opE5gVJbWsZHLETucV2wV+kDvnLk3" - name: Setup nantes.afpy.org include_role: name=julienpalard.nginx vars: nginx_owner: nantes-afpy-org nginx_path: /var/www/nantes.afpy.org nginx_domain: nantes.afpy.org nginx_certificates: [nantes.afpy.org] nginx_public_deploy_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGsky9ccA9SkMbFpaL9yEwLUW6y320kmwoCdGVCsWd3L" handlers: - name: reload nginx service: name=nginx state=reloaded