From 40db88c25664bb1d50397ff1a444fcd2f7b1e5b9 Mon Sep 17 00:00:00 2001 From: Jim Martens Date: Tue, 1 Aug 2023 09:14:40 +0200 Subject: [PATCH] Finished setup for drone server --- ansible/devops.yaml | 12 ++++ .../servers/servers_vars.yaml.example | 5 ++ ansible/inventories/hetzner.example | 5 +- ansible/roles/apache/handlers/main.yml | 9 +++ ansible/roles/apache/meta/main.yaml | 3 + ansible/roles/apache/tasks/main.yml | 42 ++++++++++++++ ansible/roles/common/tasks/main.yaml | 9 +++ ansible/roles/docker/handlers/main.yml | 5 ++ ansible/roles/docker/meta/main.yaml | 3 + ansible/roles/docker/tasks/main.yml | 24 ++++++++ .../templates/etc/docker/daemon.json.j2 | 7 +++ ansible/roles/drone/defaults/main.yaml | 2 + ansible/roles/drone/meta/main.yml | 5 ++ ansible/roles/drone/tasks/apache.yml | 56 +++++++++++++++++++ ansible/roles/drone/tasks/drone.yml | 42 ++++++++++++++ ansible/roles/drone/tasks/main.yml | 5 ++ .../ansible_domain-le-ssl.conf.j2 | 23 ++++++++ .../sites-available/ansible_domain.conf.j2 | 6 ++ .../templates/etc/drone/docker-compose.yml.j2 | 41 ++++++++++++++ ansible/roles/letsencrypt/tasks/main.yml | 9 +++ ansible/roles/server-setup/defaults/main.yaml | 2 +- .../server-setup/tasks/create-server.yaml | 6 +- ansible/roles/server-setup/tasks/main.yaml | 3 +- ansible/setup.yaml | 6 -- ansible/site.yaml | 2 +- 25 files changed, 319 insertions(+), 13 deletions(-) create mode 100644 ansible/devops.yaml create mode 100644 ansible/inventories/group_vars/servers/servers_vars.yaml.example create mode 100644 ansible/roles/apache/handlers/main.yml create mode 100644 ansible/roles/apache/meta/main.yaml create mode 100644 ansible/roles/apache/tasks/main.yml create mode 100644 ansible/roles/common/tasks/main.yaml create mode 100644 ansible/roles/docker/handlers/main.yml create mode 100644 ansible/roles/docker/meta/main.yaml create mode 100644 ansible/roles/docker/tasks/main.yml create mode 100644 ansible/roles/docker/templates/etc/docker/daemon.json.j2 create mode 100644 ansible/roles/drone/defaults/main.yaml create mode 100644 ansible/roles/drone/meta/main.yml create mode 100644 ansible/roles/drone/tasks/apache.yml create mode 100644 ansible/roles/drone/tasks/drone.yml create mode 100644 ansible/roles/drone/tasks/main.yml create mode 100644 ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain-le-ssl.conf.j2 create mode 100644 ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain.conf.j2 create mode 100644 ansible/roles/drone/templates/etc/drone/docker-compose.yml.j2 create mode 100644 ansible/roles/letsencrypt/tasks/main.yml delete mode 100644 ansible/setup.yaml diff --git a/ansible/devops.yaml b/ansible/devops.yaml new file mode 100644 index 0000000..03fde7c --- /dev/null +++ b/ansible/devops.yaml @@ -0,0 +1,12 @@ +--- +- name: Create server + hosts: localhost + roles: + - server-setup +- name: Set up drone + hosts: servers + become: true + become_method: ansible.builtin.sudo + remote_user: "{{ ssh_user }}" + roles: + - drone diff --git a/ansible/inventories/group_vars/servers/servers_vars.yaml.example b/ansible/inventories/group_vars/servers/servers_vars.yaml.example new file mode 100644 index 0000000..5668722 --- /dev/null +++ b/ansible/inventories/group_vars/servers/servers_vars.yaml.example @@ -0,0 +1,5 @@ +--- +hcloud_api_token: someAPIToken +ssh_user: remoteUser +admin_mail: mail@example.com +ci_domain: yourDomainForCi \ No newline at end of file diff --git a/ansible/inventories/hetzner.example b/ansible/inventories/hetzner.example index 4af05bb..174fbc1 100644 --- a/ansible/inventories/hetzner.example +++ b/ansible/inventories/hetzner.example @@ -1 +1,4 @@ -localhost ansible_python_interpreter=/usr/bin/python3 +localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3 + +[servers] +alias ansible_host=IPorDomain ansible_python_interpreter=python3 \ No newline at end of file diff --git a/ansible/roles/apache/handlers/main.yml b/ansible/roles/apache/handlers/main.yml new file mode 100644 index 0000000..1092b0e --- /dev/null +++ b/ansible/roles/apache/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: Restart apache + ansible.builtin.service: + name: apache2 + state: restarted +- name: Reload apache + ansible.builtin.service: + name: apache2 + state: reloaded diff --git a/ansible/roles/apache/meta/main.yaml b/ansible/roles/apache/meta/main.yaml new file mode 100644 index 0000000..950e3ed --- /dev/null +++ b/ansible/roles/apache/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: letsencrypt diff --git a/ansible/roles/apache/tasks/main.yml b/ansible/roles/apache/tasks/main.yml new file mode 100644 index 0000000..d86c643 --- /dev/null +++ b/ansible/roles/apache/tasks/main.yml @@ -0,0 +1,42 @@ +--- +- name: Install apache 2 + ansible.builtin.apt: + name: apache2 + update_cache: true + tags: + - apache +- name: Allow apache through firewall + community.general.ufw: + name: Apache Full + rule: allow +- name: Enable mods + block: + - name: Enable headers + community.general.apache2_module: + name: headers + state: present + - name: Enable proxy + community.general.apache2_module: + name: proxy + state: present + - name: Enable proxy_wstunnel + community.general.apache2_module: + name: proxy_wstunnel + state: present + - name: Enable proxy_http + community.general.apache2_module: + name: proxy_http + state: present + - name: Enable proxy_balancer + community.general.apache2_module: + name: proxy_balancer + state: present + - name: Enable lbmethod_byrequests + community.general.apache2_module: + name: lbmethod_byrequests + state: present + - name: Enable ssl + community.general.apache2_module: + name: ssl + state: present + notify: Restart apache diff --git a/ansible/roles/common/tasks/main.yaml b/ansible/roles/common/tasks/main.yaml new file mode 100644 index 0000000..5cd13ff --- /dev/null +++ b/ansible/roles/common/tasks/main.yaml @@ -0,0 +1,9 @@ +--- +- name: Ensure all tool packages are installed + ansible.builtin.apt: + pkg: "{{ packages }}" + update_cache: true + cache_valid_time: 600 + vars: + packages: + - python3-pip diff --git a/ansible/roles/docker/handlers/main.yml b/ansible/roles/docker/handlers/main.yml new file mode 100644 index 0000000..07aa0eb --- /dev/null +++ b/ansible/roles/docker/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart docker + ansible.builtin.service: + name: docker + state: restarted diff --git a/ansible/roles/docker/meta/main.yaml b/ansible/roles/docker/meta/main.yaml new file mode 100644 index 0000000..fdda41b --- /dev/null +++ b/ansible/roles/docker/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: common diff --git a/ansible/roles/docker/tasks/main.yml b/ansible/roles/docker/tasks/main.yml new file mode 100644 index 0000000..147f08a --- /dev/null +++ b/ansible/roles/docker/tasks/main.yml @@ -0,0 +1,24 @@ +--- +- name: Install docker-compose + ansible.builtin.apt: + name: docker-compose + update_cache: true + tags: + - docker +- name: Enable docker service + ansible.builtin.service: + name: docker + enabled: true +- name: Install ansible python dependencies on remote + ansible.builtin.pip: + name: + - docker + - docker-compose +- name: Enable docker log rotation + ansible.builtin.template: + src: etc/docker/daemon.json.j2 + dest: /etc/docker/daemon.json + owner: root + group: root + mode: "644" + notify: Restart docker diff --git a/ansible/roles/docker/templates/etc/docker/daemon.json.j2 b/ansible/roles/docker/templates/etc/docker/daemon.json.j2 new file mode 100644 index 0000000..b8ab8c9 --- /dev/null +++ b/ansible/roles/docker/templates/etc/docker/daemon.json.j2 @@ -0,0 +1,7 @@ +{ + "log-driver": "json-file", + "log-opts": { + "max-size": "10m", + "max-file": "3" + } +} diff --git a/ansible/roles/drone/defaults/main.yaml b/ansible/roles/drone/defaults/main.yaml new file mode 100644 index 0000000..50e0c30 --- /dev/null +++ b/ansible/roles/drone/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +drone_max_procs: 1 diff --git a/ansible/roles/drone/meta/main.yml b/ansible/roles/drone/meta/main.yml new file mode 100644 index 0000000..3821742 --- /dev/null +++ b/ansible/roles/drone/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - role: docker + - role: apache + - role: letsencrypt diff --git a/ansible/roles/drone/tasks/apache.yml b/ansible/roles/drone/tasks/apache.yml new file mode 100644 index 0000000..dc9daca --- /dev/null +++ b/ansible/roles/drone/tasks/apache.yml @@ -0,0 +1,56 @@ +--- +- name: Add drone HTTP site + ansible.builtin.template: + src: etc/apache2/sites-available/ansible_domain.conf.j2 + dest: /etc/apache2/sites-available/{{ ci_domain }}.conf + owner: root + group: root + mode: "644" + force: false + register: drone_http +- name: Disable default site and enable drone site + block: + - name: Disable default site + ansible.builtin.command: + cmd: a2dissite 000-default.conf + removes: /etc/apache2/sites-enabled/000-default.conf + - name: Enable drone site + ansible.builtin.command: + cmd: a2ensite {{ ci_domain }}.conf + creates: /etc/apache2/sites-enabled/{{ ci_domain }}.conf +- name: Check certificate existence + ansible.builtin.stat: + path: "/etc/letsencrypt/live/{{ ci_domain }}/cert.pem" + register: certificate +- name: Generate certificates + ansible.builtin.command: + cmd: > + certbot --apache --non-interactive --keep-until-expiring + --no-eff-email + --email {{ admin_mail }} + --redirect + --renew-with-new-domains --agree-tos -d {{ ci_domain }} + creates: "/etc/letsencrypt/live/{{ ci_domain }}/cert.pem" + register: certbot_certificate_created + failed_when: + - "'Successfully received certificate.' not in certbot_certificate_created.stdout" + when: + - not certificate.stat.exists +- name: Add drone HTTPS site + ansible.builtin.template: + src: etc/apache2/sites-available/ansible_domain-le-ssl.conf.j2 + dest: /etc/apache2/sites-available/{{ ci_domain }}-le-ssl.conf + owner: root + group: root + mode: "644" +- name: Check certificate existence after certbot run + ansible.builtin.stat: + path: "/etc/letsencrypt/live/{{ ci_domain }}/cert.pem" + register: certificate_after_certbot +- name: Enable drone HTTPS site + ansible.builtin.command: + cmd: a2ensite {{ ci_domain }}-le-ssl.conf + creates: /etc/apache2/sites-enabled/{{ ci_domain }}-le-ssl.conf + notify: Restart apache + when: + - certificate_after_certbot.stat.exists diff --git a/ansible/roles/drone/tasks/drone.yml b/ansible/roles/drone/tasks/drone.yml new file mode 100644 index 0000000..7160a8c --- /dev/null +++ b/ansible/roles/drone/tasks/drone.yml @@ -0,0 +1,42 @@ +--- +- name: Create drone directory + ansible.builtin.file: + state: directory + path: /etc/drone + owner: root + group: root + mode: "644" +- name: Create shared secret + ansible.builtin.command: + cmd: openssl rand -hex 16 + register: drone_rpc_secret + changed_when: true +- name: Copy docker compose file for drone + ansible.builtin.template: + src: etc/drone/docker-compose.yml.j2 + dest: /etc/drone/docker-compose.yml + owner: root + group: root + mode: "644" +- name: Start drone docker container + community.docker.docker_compose: + project_src: /etc/drone +- name: Install drone cli + block: + - name: Download drone cli + ansible.builtin.get_url: + url: https://github.com/drone/drone-cli/releases/latest/download/drone_linux_amd64.tar.gz + dest: /home/{{ ssh_user }}/drone_linux_amd64.tar.gz + owner: "{{ ssh_user }}" + group: "{{ ssh_user }}" + mode: "644" + - name: Unpack the cli archive + ansible.builtin.unarchive: + dest: /home/{{ ssh_user }} + src: /home/{{ ssh_user }}/drone_linux_amd64.tar.gz + remote_src: true + register: drone_unpack + - name: Install drone cli + ansible.builtin.command: + cmd: install -t /usr/local/bin /home/{{ ssh_user }}/drone + changed_when: true diff --git a/ansible/roles/drone/tasks/main.yml b/ansible/roles/drone/tasks/main.yml new file mode 100644 index 0000000..29a7177 --- /dev/null +++ b/ansible/roles/drone/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Set up apache for drone + ansible.builtin.import_tasks: apache.yml +- name: Set up drone + ansible.builtin.import_tasks: drone.yml diff --git a/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain-le-ssl.conf.j2 b/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain-le-ssl.conf.j2 new file mode 100644 index 0000000..2f355e2 --- /dev/null +++ b/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain-le-ssl.conf.j2 @@ -0,0 +1,23 @@ + + + ServerName {{ ci_domain }} + ServerAdmin {{ admin_mail }} + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + SSLCertificateFile /etc/letsencrypt/live/{{ ci_domain }}/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/{{ ci_domain }}/privkey.pem + Include /etc/letsencrypt/options-ssl-apache.conf + + # Encoded slashes need to be allowed + AllowEncodedSlashes NoDecode + + # keep the host + ProxyPreserveHost On + RequestHeader set X-Forwarded-Proto "https" + RequestHeader set X-Forwarded-Host "{{ ci_domain }}" + ProxyPass / http://127.0.0.1:8000/ + ProxyPassReverse / http://127.0.0.1:8000/ + + + diff --git a/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain.conf.j2 b/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain.conf.j2 new file mode 100644 index 0000000..dfd6bb4 --- /dev/null +++ b/ansible/roles/drone/templates/etc/apache2/sites-available/ansible_domain.conf.j2 @@ -0,0 +1,6 @@ + + ServerName {{ ci_domain }} + ServerAdmin {{ admin_mail }} + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + diff --git a/ansible/roles/drone/templates/etc/drone/docker-compose.yml.j2 b/ansible/roles/drone/templates/etc/drone/docker-compose.yml.j2 new file mode 100644 index 0000000..2742d5e --- /dev/null +++ b/ansible/roles/drone/templates/etc/drone/docker-compose.yml.j2 @@ -0,0 +1,41 @@ +version: '2' + +services: + drone-server: + image: drone/drone:latest + + ports: + - "8000:80" + - "8001:443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/drone:/data + restart: always + environment: + - DRONE_SERVER_HOST={{ ci_domain }} + - DRONE_SERVER_PROTO=https + - DRONE_AGENTS_ENABLED=true + - DRONE_RPC_SECRET={{ drone_rpc_secret.stdout }} + - DRONE_USER_CREATE=username:{{ gitea_user }},admin:true + - DRONE_GITEA_SERVER={{ gitea_url }} + - DRONE_GITEA_CLIENT_ID={{ gitea_client_id }} + - DRONE_GITEA_CLIENT_SECRET={{ gitea_client_secret }} + - DOCKER_MAX_PROCS={{ drone_max_procs }} + - LC_ALL=C.UTF-8 + - LANG=C.UTF-8 + drone-runner: + image: drone/drone-runner-docker:latest + + ports: + - "3000:3000" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + restart: always + depends_on: + - drone-server + environment: + - DRONE_RPC_PROTO=http + - DRONE_RPC_HOST=drone-server + - DRONE_RPC_SECRET={{ drone_rpc_secret.stdout }} + - DRONE_RUNNER_CAPACITY=2 + - DRONE_RUNNER_NAME={{ ansible_hostname }} diff --git a/ansible/roles/letsencrypt/tasks/main.yml b/ansible/roles/letsencrypt/tasks/main.yml new file mode 100644 index 0000000..4bf8f28 --- /dev/null +++ b/ansible/roles/letsencrypt/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- name: Install certbot + ansible.builtin.apt: + name: certbot + update_cache: true +- name: Install python3-certbot-apache + ansible.builtin.apt: + name: python3-certbot-apache + update_cache: true diff --git a/ansible/roles/server-setup/defaults/main.yaml b/ansible/roles/server-setup/defaults/main.yaml index 7023c5a..ff9f62d 100644 --- a/ansible/roles/server-setup/defaults/main.yaml +++ b/ansible/roles/server-setup/defaults/main.yaml @@ -3,4 +3,4 @@ basic_firewall: basic-firewall server_image: ubuntu-22.04 server_location: fsn1 server_placement_group: default -server_type: cax11 \ No newline at end of file +server_type: cax11 diff --git a/ansible/roles/server-setup/tasks/create-server.yaml b/ansible/roles/server-setup/tasks/create-server.yaml index f22ad0b..f1e50e3 100644 --- a/ansible/roles/server-setup/tasks/create-server.yaml +++ b/ansible/roles/server-setup/tasks/create-server.yaml @@ -1,11 +1,11 @@ --- -- name: create SSH key +- name: Create SSH key hetzner.hcloud.hcloud_ssh_key: api_token: "{{ hcloud_api_token }}" public_key: "{{ ssh_key_admin_user }}" name: "{{ ssh_key_admin_user_name }}" state: present -- name: create server via HCloud +- name: Create server via HCloud hetzner.hcloud.hcloud_server: api_token: "{{ hcloud_api_token }}" firewalls: @@ -19,4 +19,4 @@ - "{{ ssh_key_admin_user_name }}" user_data: "{{ lookup('ansible.builtin.template', 'basic-ssh-hardening.yaml.j2', convert_data=false) }}" state: present - register: server \ No newline at end of file + register: server diff --git a/ansible/roles/server-setup/tasks/main.yaml b/ansible/roles/server-setup/tasks/main.yaml index 476b218..07e9c10 100644 --- a/ansible/roles/server-setup/tasks/main.yaml +++ b/ansible/roles/server-setup/tasks/main.yaml @@ -1,2 +1,3 @@ --- -- import_tasks: create-server.yaml \ No newline at end of file +- name: Create server + ansible.builtin.import_tasks: create-server.yaml diff --git a/ansible/setup.yaml b/ansible/setup.yaml deleted file mode 100644 index 5ab8d79..0000000 --- a/ansible/setup.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Create server - hosts: localhost - connection: local - roles: - - server-setup diff --git a/ansible/site.yaml b/ansible/site.yaml index e78e4eb..5c62693 100644 --- a/ansible/site.yaml +++ b/ansible/site.yaml @@ -1,2 +1,2 @@ --- -- include: setup.yaml \ No newline at end of file +- include: devops.yaml \ No newline at end of file