Moving CTFd to eqy.fr
This commit is contained in:
parent
3f8652723a
commit
c370d57c7a
141
ctfd.yml
141
ctfd.yml
|
@ -1,8 +1,141 @@
|
|||
---
|
||||
|
||||
- hosts: mdk
|
||||
roles: ["julienpalard.ctfd"]
|
||||
- hosts: ctfd
|
||||
vars:
|
||||
domain: ctf.mdk.fr
|
||||
domain: ctf.eqy.fr
|
||||
owner: ctfd
|
||||
version: master
|
||||
home: "/home/ctfd"
|
||||
letsencrypt_email: julien@palard.fr
|
||||
secret_key: "{{ vault_ctfd_secret }}"
|
||||
secret_key: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
34396134346435343464653766663833643061666164323337646137636631643930326633333239
|
||||
3433333563366461646665643739383466343465663733650a326533316138366336333231616162
|
||||
62623562346561663936303861363863626336343437333164343063323533353432653766356334
|
||||
6138343864666637660a383165356630363533376562323663353636373636613035636339626631
|
||||
31643062353434333534333130636237396365633662343964666134333833373439363833323062
|
||||
3032666163643162613766306437356438653538333163346531
|
||||
tasks:
|
||||
- name: Create user
|
||||
user:
|
||||
name: "{{ owner }}"
|
||||
home: "{{ home }}"
|
||||
|
||||
- name: Clone ctfd
|
||||
git:
|
||||
repo: https://github.com/CTFd/CTFd
|
||||
dest: "{{ home }}/CTFd/"
|
||||
become: true
|
||||
become_user: "{{ owner }}"
|
||||
|
||||
- name: Setup secret key
|
||||
copy:
|
||||
content: "{{ secret_key }}"
|
||||
dest: "{{ home }}/CTFd/.ctfd_secret_key"
|
||||
|
||||
- name: Configure nginx
|
||||
include_role: name=nginx
|
||||
vars:
|
||||
nginx_domain: "{{ domain }}"
|
||||
nginx_certificates:
|
||||
- "{{ domain }}"
|
||||
nginx_owner: "{{ owner }}"
|
||||
nginx_conf: |
|
||||
server
|
||||
{
|
||||
listen 80;
|
||||
server_name {{ domain }};
|
||||
access_log /var/log/nginx/{{ domain }}-access.log;
|
||||
error_log /var/log/nginx/{{ domain }}-error.log;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server
|
||||
{
|
||||
listen 443 ssl;
|
||||
server_name {{ domain }};
|
||||
access_log /var/log/nginx/{{ domain }}-access.log;
|
||||
error_log /var/log/nginx/{{ domain }}-error.log;
|
||||
include snippets/letsencrypt-{{ domain }}.conf;
|
||||
|
||||
add_header X-Frame-Options DENY;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
location /
|
||||
{
|
||||
proxy_pass http://unix:{{ home }}/ctfd.sock;
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
|
||||
- name: Install requirements
|
||||
pip:
|
||||
requirements: "{{ home }}/CTFd/requirements.txt"
|
||||
virtualenv_command: "/usr/bin/python3 -m venv"
|
||||
virtualenv: "{{ home }}/venv/"
|
||||
become: true
|
||||
become_user: "{{ owner }}"
|
||||
|
||||
- name: Install MariaDB
|
||||
# CTFd can run on SQLite but with migration issues
|
||||
# See #1988.
|
||||
package:
|
||||
state: present
|
||||
name:
|
||||
- mariadb-server
|
||||
- python3-pymysql
|
||||
|
||||
- name: MariaDB database
|
||||
community.mysql.mysql_db:
|
||||
name: ctfd
|
||||
state: present
|
||||
login_unix_socket: /run/mysqld/mysqld.sock
|
||||
|
||||
- name: MariaDB user
|
||||
community.mysql.mysql_user:
|
||||
state: present
|
||||
name: ctfd
|
||||
priv: 'ctfd.*:ALL'
|
||||
login_unix_socket: /run/mysqld/mysqld.sock
|
||||
|
||||
- name: Configure CTFd to use MariaDB
|
||||
lineinfile:
|
||||
path: '/home/ctfd/CTFd/CTFd/config.ini'
|
||||
regex: '^DATABASE_URL'
|
||||
line: 'DATABASE_URL = mysql+pymysql://ctfd@/ctfd?unix_socket=/run/mysqld/mysqld.sock'
|
||||
notify: Restart CTFd
|
||||
|
||||
- name: Configure systemd
|
||||
copy:
|
||||
dest: "/etc/systemd/system/{{ domain }}.service"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=CTFd ({{ domain }})
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
PIDFile={{ home }}/gunicorn.pid
|
||||
User={{ owner }}
|
||||
Group={{ owner }}
|
||||
RuntimeDirectory=pasteque
|
||||
WorkingDirectory={{ home }}/CTFd/
|
||||
ExecStart={{ home }}/venv/bin/gunicorn --worker-class gevent -w6 -t 120 --pid {{ home }}/gunicorn.pid \
|
||||
--bind unix:{{ home }}/ctfd.sock wsgi:app
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
ExecStop=/bin/kill -s TERM $MAINPID
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- name: Start CTFd
|
||||
service: name="{{ domain }}" enabled=yes state=started daemon_reload=yes
|
||||
|
||||
handlers:
|
||||
- name: Restart CTFd
|
||||
service: name=ctf.eqy.fr state=restarted
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
|
||||
admin_email: julien@palard.fr
|
||||
gandi_api_key: "{{ vault_gandi_api_key }}"
|
|
@ -0,0 +1,8 @@
|
|||
$ANSIBLE_VAULT;1.1;AES256
|
||||
61333239366432343130623339303039336432376630396530656333646231346230383066646137
|
||||
6137386633646634653864366235613435633033653961330a616130353838333863346536653565
|
||||
31666161386231353038343066633533323866326532343832666135366537393966366461653763
|
||||
3864646630653463610a373063346431393464383739643336663239623533626530653332623631
|
||||
64396532656633363236633461323361313833373538373261386530653339313235633562336638
|
||||
62643237623933663732366533363635616339646265633961333037393438373231613364623939
|
||||
636464383531656363306435643365313765
|
|
@ -3,6 +3,10 @@ all:
|
|||
ansible_user: root
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
children:
|
||||
ctfd:
|
||||
hosts:
|
||||
eqy.fr:
|
||||
ansible_host: 163.172.82.132
|
||||
mdk:
|
||||
hosts:
|
||||
mdk.fr:
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# Nginx with Letsencrypt
|
||||
|
||||
This role sets up nginx with letsencrypt (using DNS-01 with Gandi API) .
|
||||
|
||||
|
||||
## Role Variables
|
||||
|
||||
The mandatory variables are:
|
||||
|
||||
- `admin_email`: For letsencrypt.
|
||||
- `gandi_api_key` ([see doc](https://github.com/obynio/certbot-plugin-gandi/)).
|
||||
- `nginx_certificates`: A list of domain to put in this certificate.
|
||||
- `nginx_domain`: Used for file names, certificate name, and default server_name if no nginx_conf is given.
|
||||
- `nginx_conf`: The nginx config.
|
||||
|
||||
Optional variables are:
|
||||
|
||||
- `nginx_owner`: If a unix user has to be created for this project.
|
||||
- `nginx_path`: To create a directory owned by `nginx_owner`.
|
||||
- `ssl_ciphers`: [Specifies the enabled ciphers](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers).
|
||||
- `ssl_protocols`: [Enables the specified protocols.](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols)
|
||||
- `ssl_prefer_server_ciphers`: [Specifies that server ciphers should be preferred over client ciphers when using the SSLv3 and TLS protocols.](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers)
|
||||
- `ssl_session_cache`: [Sets the types and sizes of caches that store session parameters.](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache).
|
||||
- `HSTS_header`: HTTP header to inject.
|
||||
|
||||
|
||||
### Author Information
|
||||
|
||||
Julien Palard — https://mdk.fr
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
|
||||
ssl_protocols: "TLSv1.2 TLSv1.3"
|
||||
ssl_prefer_server_ciphers: "off"
|
||||
ssl_session_cache: "shared:ssl_session_cache:10m"
|
||||
HSTS_header: 'Strict-Transport-Security "max-age=63072000; always"'
|
||||
nginx_conf: |
|
||||
server
|
||||
{
|
||||
listen [::]:80; listen 80;
|
||||
server_name {{ nginx_domain }};
|
||||
access_log /var/log/nginx/{{ nginx_domain }}-access.log;
|
||||
error_log /var/log/nginx/{{ nginx_domain }}-error.log;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server
|
||||
{
|
||||
listen [::]:443 ssl; listen 443 ssl;
|
||||
charset utf-8;
|
||||
server_name {{ nginx_domain }};
|
||||
access_log /var/log/nginx/{{ nginx_domain }}-access.log;
|
||||
error_log /var/log/nginx/{{ nginx_domain }}-error.log;
|
||||
include snippets/letsencrypt-{{ nginx_domain }}.conf;
|
||||
|
||||
root {{ nginx_path }};
|
||||
index index.html;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
- name: reload nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
|
||||
- name: Create SSL dhparam
|
||||
get_url:
|
||||
url: https://ssl-config.mozilla.org/ffdhe2048.txt
|
||||
dest: /etc/ssl/certs/dhparam.pem
|
||||
mode: 0644
|
||||
|
||||
- name: Prepare certbot+gandi venv
|
||||
pip:
|
||||
chdir: /root/
|
||||
virtualenv_command: /usr/bin/python3 -m venv
|
||||
virtualenv: /root/certbot-venv/
|
||||
name:
|
||||
- "pip>=21.0.1"
|
||||
- "setuptools>=53.0.0"
|
||||
- "wheel>=0.36.2"
|
||||
|
||||
- name: Install certbot+gandi in venv
|
||||
pip:
|
||||
chdir: /root/
|
||||
virtualenv_command: /usr/bin/python3 -m venv
|
||||
virtualenv: /root/certbot-venv/
|
||||
name:
|
||||
- certbot
|
||||
- certbot-plugin-gandi
|
||||
|
||||
- name: Setup Gandi credentials
|
||||
copy:
|
||||
content: |
|
||||
dns_gandi_api_key = {{ gandi_api_key }}
|
||||
mode: 0600
|
||||
dest: /root/gandi.ini
|
||||
|
||||
- name: Generate TLS certificates
|
||||
command: /root/certbot-venv/bin/certbot certonly --cert-name {{ nginx_domain | quote }} -n --agree-tos -d {{ nginx_certificates | join(",") | quote }} -m {{ admin_email | quote }} --authenticator dns-gandi --dns-gandi-credentials /root/gandi.ini
|
||||
register: certbot
|
||||
changed_when: '"no action taken." not in certbot.stdout'
|
||||
|
||||
- name: Setup renewal cron
|
||||
cron:
|
||||
name: certbot
|
||||
minute: "55"
|
||||
hour: "8"
|
||||
job: '/root/certbot-venv/bin/certbot -q renew'
|
||||
|
||||
- name: Setup PATH in renewal cron
|
||||
ansible.builtin.cron:
|
||||
name: PATH
|
||||
env: yes
|
||||
job: /usr/sbin
|
||||
|
||||
- name: Setup renewal hook directory
|
||||
file:
|
||||
path: /etc/letsencrypt/renewal-hooks/post
|
||||
state: directory
|
||||
mode: 0755
|
||||
|
||||
- name: Setup renewal hook script
|
||||
copy:
|
||||
dest: /etc/letsencrypt/renewal-hooks/deploy/nginx.sh
|
||||
mode: 0755
|
||||
content: |
|
||||
#!/bin/sh
|
||||
/usr/bin/systemctl reload nginx
|
||||
|
||||
- name: Install nginx
|
||||
package:
|
||||
state: present
|
||||
name:
|
||||
- nginx
|
||||
- ca-certificates
|
||||
|
||||
- name: Ensure certbot is not installed from Debian packages
|
||||
package:
|
||||
state: absent
|
||||
name:
|
||||
- certbot
|
||||
- python-certbot-nginx
|
||||
- python3-certbot-nginx
|
||||
|
||||
- name: Create letsencrypt snippets
|
||||
template:
|
||||
src: letsencrypt.conf.j2
|
||||
dest: '/etc/nginx/snippets/letsencrypt-{{ nginx_domain }}.conf'
|
||||
|
||||
- name: User
|
||||
user:
|
||||
system: true
|
||||
name: "{{ nginx_owner }}"
|
||||
when: nginx_owner is defined
|
||||
|
||||
- name: .ssh directory
|
||||
file:
|
||||
path: "~{{ nginx_owner }}/.ssh"
|
||||
state: directory
|
||||
owner: "{{ nginx_owner }}"
|
||||
mode: 0755
|
||||
when: nginx_owner is defined
|
||||
|
||||
- name: Deploy key
|
||||
blockinfile:
|
||||
create: true
|
||||
owner: "{{ nginx_owner }}"
|
||||
mode: 0644
|
||||
path: "~{{ nginx_owner }}/.ssh/authorized_keys"
|
||||
marker: "<!-- {mark} ANSIBLE MANAGED BLOCK: Deploy key for {{ nginx_domain }} -->"
|
||||
block: "{{ nginx_public_deploy_key }}"
|
||||
when: nginx_owner is defined and nginx_public_deploy_key is defined
|
||||
|
||||
- name: Configure nginx
|
||||
copy:
|
||||
content: "{{ nginx_conf }}"
|
||||
dest: "/etc/nginx/conf.d/{{ nginx_domain }}.conf"
|
||||
notify: reload nginx
|
||||
|
||||
- name: WWW directory
|
||||
file:
|
||||
path: "{{ nginx_path }}"
|
||||
state: directory
|
||||
owner: "{{ nginx_owner }}"
|
||||
group: "{{ nginx_owner }}"
|
||||
mode: 0755
|
||||
when: nginx_owner is defined and nginx_path is defined
|
|
@ -0,0 +1,21 @@
|
|||
# Inspired from
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.6
|
||||
ssl_ciphers "{{ ssl_ciphers }}";
|
||||
ssl_protocols {{ ssl_protocols }};
|
||||
ssl_prefer_server_ciphers {{ ssl_prefer_server_ciphers }};
|
||||
|
||||
ssl_session_cache {{ ssl_session_cache }};
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/{{ nginx_domain }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ nginx_domain }}/privkey.pem;
|
||||
ssl_dhparam /etc/ssl/certs/dhparam.pem;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
|
||||
|
||||
{% if HSTS_header %}
|
||||
add_header {{ HSTS_header }};
|
||||
{% endif %}
|
Loading…
Reference in New Issue