diff --git a/TODO.md b/TODO.md index 0ba2116..1555688 100644 --- a/TODO.md +++ b/TODO.md @@ -46,4 +46,8 @@ setup: - Potgres role should be redone, it is currently called too many times that could be globalized I think. Also the setting of timezone and locale is not idempotent +## Disks + +- Do a real role to setup the disks. Maybe use LVM when zfs is not in use? + good luck diff --git a/ansible.cfg b/ansible.cfg index 960b7ef..01c6eae 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -28,6 +28,7 @@ vault_identity = default [privilege_escalation] # Use sudo to get priviledge access become = True +#become_ask_pass = True [diff] # TO know what changed diff --git a/books/hypervisor.yml b/books/hypervisor.yml index bdeceee..058f37f 100755 --- a/books/hypervisor.yml +++ b/books/hypervisor.yml @@ -3,5 +3,5 @@ - hosts: proxmox roles: - # - proxmox + - proxmox - zfs diff --git a/books/matrix.yml b/books/matrix.yml index 94c47e4..b5db8dd 100755 --- a/books/matrix.yml +++ b/books/matrix.yml @@ -3,7 +3,7 @@ - hosts: synapse roles: - synapse - - matrix-bridge-discord + #- matrix-bridge-discord - matrix-bridge-facebook - matrix-bridge-signal - matrix-bridge-instagram diff --git a/books/pterodactyl.yml b/books/pterodactyl.yml new file mode 100755 index 0000000..7c51e16 --- /dev/null +++ b/books/pterodactyl.yml @@ -0,0 +1,8 @@ +#!/usr/bin/env ansible-playbook +--- + +- hosts: pterodactyl + roles: + - disks + - pterodactyl-panel + - pterodactyl-wings diff --git a/group_vars/pterodactyl/main.yml b/group_vars/pterodactyl/main.yml new file mode 100644 index 0000000..72c9669 --- /dev/null +++ b/group_vars/pterodactyl/main.yml @@ -0,0 +1,4 @@ +--- + +pterodactyl_email: "ssl@nyx.ovh" +pterodactyl_domain: "play.nyx.ovh" diff --git a/group_vars/pterodactyl/secrets.yml b/group_vars/pterodactyl/secrets.yml new file mode 100644 index 0000000..953f652 --- /dev/null +++ b/group_vars/pterodactyl/secrets.yml @@ -0,0 +1,42 @@ +$ANSIBLE_VAULT;1.1;AES256 +61666639363338363935636238616235366166343962643065346333373164613438663932636365 +6232636166643864393135626461333861323665386564340a643732356362393637346631336162 +34656363656663303363653532346666323731376135663337353462316631636433373635353466 +6666633064633634640a366264626338643566333964316237626634613538373731386637363265 +61663139376161613834653037653832306236333739613265306363323535663961663464636464 +37663965373637383962326138373138386330323334333430353231313730313130333034366430 +66396333626339623264303538633039386130316234346530323138386665376435616162653863 +39326665656165336534356430323561643339646161333335353062313766376565386332303964 +66643137343464343763356533353832333232653838373531396232623536616233326330643332 +63633632313166633064353837353931373363623137326231616365663262343334616663396337 +65663162396230343064663231393038663461363031306162346264363861333938663137393038 +31633139336237623736636538303563326236666332333939653835303062663964666335303636 +30326163343864373038343864323261613264393937333666336662306563633764666264623533 +39306661373036393432353837373763383839336135643239366665353263383730613862353866 +39313964613066363166303335333563373339333736376633386637353734663739643431393233 +36336533313061316335616438356237346239663331653530373237346238333233623464373364 +65303466313237616235383562313065623235653031306262386434363166363533653430363462 +38333538343435363666656339363965373736303263366536363264623234336566656233313732 +38613234653032393636396537653366306330366233623861393036623731616633653232346136 +34613062303863396632646165663665313332346333323539613630613539633561666262346530 +65616235376431643436626637636638306164306430643031646537313661316531623837663232 +66626161656337623666373832613465303265313465306233616334346566343036336134613065 +34306264326262306637356131376465323538386164633966303666316632626361383464633437 +65383539353666343132666635663930613938613064633239303761343831666339363438393637 +39626636356137306530333235633861313536373039616164313764323866356261643534646364 +38303433653138396338663631616338333932343232353536373635613434646536333330373931 +62313164656165303736353766653937326265316139306564653836326438663539633430646261 +63383739656464376534326161323331306263303432646136613332646533393730313638316537 +30333437636461373932643533616262323161353438303734386136626233396262346432643966 +65343866376539373735636136376364306538373338313732326233613236626661653131313866 +36343739653762396335623031326530393635303832393834326236633562613466303538656664 +66376632343963373533383763353132636233623633373133663336666233643731386634386536 +65616239356438346434366634623661343263633334356132373435653338323230323236313130 +35623739346130373663663431373831623065643965373830613736383933616637653239633965 +65663262356463346638346538636566313436663762303035383436613262343537653235613238 +36353465626362363730646666636434396561666639616633613366323964353638346331346364 +39643535663637646331383937316139663835633732383034336439613530323934323137653334 +31343839643966313366326232643232333566323239663763363432636236376238653063306263 +61666235313634366239303035353134363938326535373435346464643262353232613762306633 +30626237326136616563333161663833626266313162373065646236626466616331303662366365 +6364 diff --git a/host_vars/iridium/main.yml b/host_vars/iridium/main.yml new file mode 100644 index 0000000..1262806 --- /dev/null +++ b/host_vars/iridium/main.yml @@ -0,0 +1,22 @@ +--- +ansible_host: iridium.lan + +## Users +users: + g33kex: sudo + +## Networking +interfaces: + ens18: + type: dhcp + +ipv4_forwarding: no +ipv6_forwarding: no + +## Disks + +disks: + - device: /dev/sdb + name: data + mount_point: /data + format: ext4 diff --git a/hosts b/hosts index d1a8c19..083e8db 100644 --- a/hosts +++ b/hosts @@ -9,6 +9,7 @@ physical bismuth # BigBlueButton sulfur # Synapse technetium # Test +iridium # Pterodactyl [container] @@ -20,6 +21,7 @@ barium # Backup [cloudinit] bismuth technetium +iridium # Groups [monitoring] @@ -57,3 +59,6 @@ vanadium [backup] barium + +[pterodactyl] +iridium diff --git a/roles/disks/tasks/format_disk.yml b/roles/disks/tasks/format_disk.yml new file mode 100644 index 0000000..f4b89bf --- /dev/null +++ b/roles/disks/tasks/format_disk.yml @@ -0,0 +1,23 @@ +--- + +- name: Partition disk + community.general.parted: + device: "{{ disk.device }}" + label: gpt + number: 1 + name: "{{ disk.name }}" + fs_type: "{{ disk.format }}" + state: present + register: register_partition + +- name: Create filesystem + community.general.filesystem: + dev: "{{ disk.device }}1" + fstype: "{{ disk.format }}" + +- name: Mount disk + mount: + src: "{{ disk.device }}1" + path: "{{ disk.mount_point }}" + fstype: "{{ disk.format }}" + state: mounted diff --git a/roles/disks/tasks/main.yml b/roles/disks/tasks/main.yml new file mode 100644 index 0000000..1886a20 --- /dev/null +++ b/roles/disks/tasks/main.yml @@ -0,0 +1,12 @@ +--- + +- name: Install dependencies + apt: + name: parted + state: present + +- name: Create partitions and format disks + include_tasks: format_disk.yml + loop: "{{ disks }}" + loop_control: + loop_var: disk diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..f8aa4c0 --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,27 @@ +--- + +- name: Add the docker repo key + apt_key: + url: https://download.docker.com/linux/debian/gpg + state: present + +- name: Add docker repo + apt_repository: + repo: deb [arch=amd64] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable + state: present + +- name: Install docker and docker compose + apt: + update_cache: true + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-compose-plugin + state: latest + +- name: Start and enable docker + systemd: + name: docker.service + state: started + enabled: yes diff --git a/roles/mariadb/tasks/main.yml b/roles/mariadb/tasks/main.yml new file mode 100644 index 0000000..2a78cce --- /dev/null +++ b/roles/mariadb/tasks/main.yml @@ -0,0 +1,58 @@ +--- + +- name: Install mariadb + apt: + update_cache: yes + pkg: + - mariadb-server + - python3-pymysql + state: present + +- name: Enable and start mariadb + systemd: + name: mariadb.service + state: started + enabled: yes + +- name: Update MariaDB root password + community.mysql.mysql_user: + name: root + host_all: yes + password: "{{ mysql_root_pwd }}" + login_password: "{{ mysql_root_pwd }}" + login_unix_socket: /var/run/mysqld/mysqld.sock + +- name: Removes all anonymous user accounts + community.mysql.mysql_user: + name: '' + host_all: yes + state: absent + login_password: "{{ mysql_root_pwd }}" + login_unix_socket: /var/run/mysqld/mysqld.sock + +- name: Remove MySQL test database + mysql_db: + name: test + state: absent + login_password: "{{ mysql_root_pwd }}" + login_unix_socket: /var/run/mysqld/mysqld.sock + +- name: Create mysql databases + community.mysql.mysql_db: + name: "{{ item.name }}" + state: present + login_password: "{{ mysql_root_pwd }}" + login_unix_socket: /var/run/mysqld/mysqld.sock + loop: "{{ mysql_databases }}" + no_log: "{{ enable_no_log | default('true') }}" + +- name: Create mysql users + community.mysql.mysql_user: + name: "{{ item.name }}" + password: "{{ pterodactyl_mysql_user_pwd }}" + priv: "{{ item.priv }}" + state: present + login_password: "{{ mysql_root_pwd }}" + login_unix_socket: /var/run/mysqld/mysqld.sock + loop: "{{ mysql_users }}" + no_log: "{{ enable_no_log | default('true') }}" diff --git a/roles/pterodactyl-panel/handlers/main.yml b/roles/pterodactyl-panel/handlers/main.yml new file mode 100644 index 0000000..4e334c2 --- /dev/null +++ b/roles/pterodactyl-panel/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: Restart nginx + systemd: + name: nginx + state: restarted diff --git a/roles/pterodactyl-panel/tasks/main.yml b/roles/pterodactyl-panel/tasks/main.yml new file mode 100644 index 0000000..23bbe4a --- /dev/null +++ b/roles/pterodactyl-panel/tasks/main.yml @@ -0,0 +1,182 @@ +--- + +- name: Add domain to host file + ansible.builtin.lineinfile: + path: /etc/hosts + search_string: '127.0.0.1 {{ pterodactyl_domain }}' + line: '127.0.0.1 {{ pterodactyl_domain }}' + state: present + +- name: Setup mariadb + include_role: + name: mariadb + vars: + mysql_databases: + - name: panel + mysql_users: + - name: pterodactyl + password: "{{ pterodactyl_mysql_user_pwd }}" + priv: "panel.*:ALL,GRANT" + +- name: Install dependencies + apt: + pkg: + - curl + - tar + - unzip + - git + - redis-server + - nginx + - php + - php-cli + - php-gd + - php-mysql + - php-bcmath + - php-xml + - php-dom + - php-curl + - php-zip + - php-fpm + - composer + - certbot + - python3-certbot-nginx + update_cache: yes + state: present + +- name: Enable and start redis-server + systemd: + name: redis-server.service + state: started + enabled: yes + +- name: Download the panel + get_url: + url: "https://github.com/pterodactyl/panel/releases/latest/download/panel.tar.gz" + checksum: "sha256:https://github.com/pterodactyl/panel/releases/latest/download/checksum.txt" + dest: /var/tmp/panel.tar.gz + register: register_download + +- name: Ensure panel directory exists + file: + path: /var/www/pterodactyl/ + state: directory + register: register_directory + +- name: Enter maintenance mode if updating + command: php artisan down + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed and not register_directory.changed + +- name: Install the panel + unarchive: + src: /var/tmp/panel.tar.gz + remote_src: yes + dest: /var/www/pterodactyl/ + owner: www-data + group: www-data + +- name: Install panel dependencies + community.general.composer: + command: install + working_dir: /var/www/pterodactyl/ + optimize_autoloader: yes + no_dev: yes + +- name: Configure the panel + template: + src: env.j2 + dest: /var/www/pterodactyl/.env + owner: www-data + group: www-data + +- name: Clear view cache after update + command: php artisan view:clear + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed and not register_directory.changed + +- name: Clear config cache after update + command: php artisan config:clear + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed and not register_directory.changed + +- name: Migrate database + command: php artisan migrate --seed --force + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed + +- name: Add pterodactyl panel users + command: php artisan p:user:make -n --no-ansi --email "{{ item.email }}" --username "{{ item.username }}" --name-first "{{ item.firstname }}" --name-last "{{ item.lastname }}" --password "{{ item.password }}" --admin {{ 1 if item.admin else 0 | default(0) }} + args: + chdir: /var/www/pterodactyl/ + loop: "{{ pterodactyl_users }}" + register: register_adduser + changed_when: '"been taken" not in register_adduser.stdout' + failed_when: 'register_adduser.rc != 0 and "been taken" not in register_adduser.stdout' + no_log: "{{ enable_no_log | default('true') }}" + + +- name: Restart queue worker after update + command: php artisan queue:restart + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed and not register_directory.changed + +- name: Exit maintenance mode after update + command: php artisan up + args: + chdir: /var/www/pterodactyl/ + when: register_download.changed and not register_directory.changed + +- name: Create cron job for panel + cron: + name: "pterodactyl panel" + job: "/usr/bin/php /var/www/pterodactyl/artisan schedule:run >> /dev/null 2>&1" + month: "*" + day: "*" + hour: "*" + minute: "*" + +- name: Create pterodactyl queue worker service + template: + src: pteroq.j2 + dest: /etc/systemd/system/pteroq.service + +- name: Enable and start pterodactyl queue worker service + systemd: + name: pteroq.service + state: started + enabled: yes + +- name: Enable and start nginx + systemd: + name: nginx + state: started + enabled: yes + +- name: Generate ssl certificate with certbot + command: certbot certonly -n --nginx --email "{{ pterodactyl_email }}" --agree-tos -d "{{ pterodactyl_domain }}" + args: + creates: "/etc/letsencrypt/live/{{ pterodactyl_domain }}/fullchain.pem" + +- name: Remove default nginx config + file: + path: /etc/nginx/sites-enabled/default + state: absent + +- name: Add pterodactyl nginx config + template: + src: nginx.j2 + dest: /etc/nginx/sites-available/pterodactyl.conf + notify: Restart nginx + +- name: Enable pterodactyl nginx config + file: + src: "/etc/nginx/sites-available/pterodactyl.conf" + path: "/etc/nginx/sites-enabled/pterodactyl.conf" + state: link +notify: Restart nginx + diff --git a/roles/pterodactyl-panel/templates/env.j2 b/roles/pterodactyl-panel/templates/env.j2 new file mode 100644 index 0000000..be14218 --- /dev/null +++ b/roles/pterodactyl-panel/templates/env.j2 @@ -0,0 +1,51 @@ +{{ ansible_managed | comment }} + +APP_ENV=production +APP_DEBUG=false +APP_KEY=base64:{{ pterodactyl_app_key }} +APP_THEME=pterodactyl +APP_TIMEZONE=Europe/Paris +APP_CLEAR_TASKLOG=720 +APP_DELETE_MINUTES=10 +APP_ENVIRONMENT_ONLY=false +LOG_CHANNEL=daily +APP_LOCALE=en +APP_URL=https://{{ pterodactyl_domain }} + +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=panel +DB_USERNAME=pterodactyl +DB_PASSWORD={{ pterodactyl_mysql_user_pwd }} + +SESSION_DRIVER=redis +CACHE_DRIVER=redis + +HASHIDS_SALT={{ pterodactyl_hashids_salt }} +HASHIDS_LENGTH=8 + +MAIL_DRIVER=mail +MAIL_HOST=smtp.example.com +MAIL_PORT=25 +MAIL_USERNAME= +MAIL_PASSWORD= +MAIL_ENCRYPTION=tls +MAIL_FROM=no-reply@example.com +MAILGUN_ENDPOINT=api.mailgun.net +# You should set this to your domain to prevent it defaulting to 'localhost', causing +# mail servers such as Gmail to reject your mail. +# +# @see: https://github.com/pterodactyl/panel/pull/3110 +# SERVER_NAME=panel.example.com + +QUEUE_HIGH=high +QUEUE_STANDARD=standard +QUEUE_LOW=low + +APP_SERVICE_AUTHOR="{{ pterodactyl_email }}" +QUEUE_CONNECTION=redis +SESSION_SECURE_COOKIE=true +REDIS_HOST=localhost +REDIS_PASSWORD=null +REDIS_PORT=6379 +MAIL_FROM_NAME="Pterodactyl Panel" diff --git a/roles/pterodactyl-panel/templates/nginx.j2 b/roles/pterodactyl-panel/templates/nginx.j2 new file mode 100644 index 0000000..c170f38 --- /dev/null +++ b/roles/pterodactyl-panel/templates/nginx.j2 @@ -0,0 +1,69 @@ +{{ ansible_managed | comment }} + +server_tokens off; + +server { + listen 80; + server_name {{ pterodactyl_domain }}; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name {{ pterodactyl_domain }}; + + root /var/www/pterodactyl/public; + index index.php; + + access_log /var/log/nginx/pterodactyl.app-access.log; + error_log /var/log/nginx/pterodactyl.app-error.log error; + + # allow larger file uploads and longer script runtimes + client_max_body_size 100m; + client_body_timeout 120s; + + sendfile off; + + # SSL Configuration + ssl_certificate /etc/letsencrypt/live/{{ pterodactyl_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ pterodactyl_domain }}/privkey.pem; + ssl_session_cache shared:SSL:10m; + ssl_protocols TLSv1.2 TLSv1.3; + 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_prefer_server_ciphers on; + + # See https://hstspreload.org/ before uncommenting the line below. + # add_header Strict-Transport-Security "max-age=15768000; preload;"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Robots-Tag none; + add_header Content-Security-Policy "frame-ancestors 'self'"; + add_header X-Frame-Options DENY; + add_header Referrer-Policy same-origin; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php/php7.4-fpm.sock; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M"; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param HTTP_PROXY ""; + fastcgi_intercept_errors off; + fastcgi_buffer_size 16k; + fastcgi_buffers 4 16k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + include /etc/nginx/fastcgi_params; + } + + location ~ /\.ht { + deny all; + } +} + diff --git a/roles/pterodactyl-panel/templates/pteroq.j2 b/roles/pterodactyl-panel/templates/pteroq.j2 new file mode 100644 index 0000000..9b78501 --- /dev/null +++ b/roles/pterodactyl-panel/templates/pteroq.j2 @@ -0,0 +1,21 @@ +{{ ansible_managed | comment }} +# Pterodactyl Queue Worker File +# ---------------------------------- + +[Unit] +Description=Pterodactyl Queue Worker +After=redis-server.service + +[Service] +# On some systems the user and group might be different. +# Some systems use `apache` or `nginx` as the user and group. +User=www-data +Group=www-data +Restart=always +ExecStart=/usr/bin/php /var/www/pterodactyl/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3 +StartLimitInterval=180 +StartLimitBurst=30 +RestartSec=5s + +[Install] +WantedBy=multi-user.target diff --git a/roles/pterodactyl-wings/tasks/main.yml b/roles/pterodactyl-wings/tasks/main.yml new file mode 100644 index 0000000..844ee63 --- /dev/null +++ b/roles/pterodactyl-wings/tasks/main.yml @@ -0,0 +1,29 @@ +--- + +- name: Install docker + include_role: + name: docker + +- name: Create configuration directory + file: + path: /etc/pterodactyl + owner: root + group: root + state: directory + mode: '0755' + +- name: Install wings + get_url: + url: "https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_amd64" + dest: /usr/local/bin/wings + owner: root + group: root + mode: '0744' + +- name: Install wings service file + template: + src: wings.j2 + dest: /etc/systemd/system/wings.service + +- debug: + msg: "Please create a node in the panel's ui and add the config to /etc/pterodactyl, then enable and start wings.service" diff --git a/roles/pterodactyl-wings/templates/wings.j2 b/roles/pterodactyl-wings/templates/wings.j2 new file mode 100644 index 0000000..d7a244e --- /dev/null +++ b/roles/pterodactyl-wings/templates/wings.j2 @@ -0,0 +1,19 @@ +[Unit] +Description=Pterodactyl Wings Daemon +After=docker.service +Requires=docker.service +PartOf=docker.service + +[Service] +User=root +WorkingDirectory=/etc/pterodactyl +LimitNOFILE=4096 +PIDFile=/var/run/wings/daemon.pid +ExecStart=/usr/local/bin/wings +Restart=on-failure +StartLimitInterval=180 +StartLimitBurst=30 +RestartSec=5s + +[Install] +WantedBy=multi-user.target