thingies
This commit is contained in:
parent
5f06a966aa
commit
3343de2dc0
12 changed files with 286 additions and 57 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
inventory.ini
|
inventory.ini
|
||||||
|
venv/*
|
||||||
|
|
@ -5,7 +5,11 @@ This describes how to prepare each machine before deploying services on them.
|
||||||
## 01.01 First steps
|
## 01.01 First steps
|
||||||
|
|
||||||
* Create an ssh key or pick an existing one. We'll refer to it as the `personal_ssh_key`.
|
* Create an ssh key or pick an existing one. We'll refer to it as the `personal_ssh_key`.
|
||||||
* The guide assumes the laptop (Lapy) has `ansible` installed. If not, do `sudo apt install -y ansible` and `ansible --version` to check.
|
* Deploy ansible on the laptop (Lapy), which will act as the ansible control node. To do so:
|
||||||
|
* Create a `venv`: `python3 -m venv venv`
|
||||||
|
* Activate it: `source venv/bin/activate`
|
||||||
|
* Install the listed ansible requirements with `pip install -r requirements.txt`
|
||||||
|
* Keep in mind you should activate this `venv` from now on when running `ansible` commands.
|
||||||
|
|
||||||
## 01.02 Prepare the VPS (Vipy)
|
## 01.02 Prepare the VPS (Vipy)
|
||||||
|
|
||||||
|
|
@ -20,9 +24,13 @@ This describes how to prepare each machine before deploying services on them.
|
||||||
|
|
||||||
### 01.02.02 Prepare Ansible vars
|
### 01.02.02 Prepare Ansible vars
|
||||||
|
|
||||||
* You have an example `infra/example.inventory.ini`. Copy it with `cp example.inventory.ini inventory.ini` and fill in with the vars for your VPS.
|
* You have an example `ansible/example.inventory.ini`. Copy it with `cp ansible/example.inventory.ini ansible/inventory.ini` and fill in with the values for your VPS.
|
||||||
|
|
||||||
### 01.02.03 First steps with Ansible
|
### 01.02.03 Create user and secure VPS access
|
||||||
|
|
||||||
* cd into `infra`
|
* Ansible will create a user on the first playbook `01_basic_vps_setup_playbook.yml`. This is the user that will get used regularly. But, since this user doesn't exist, you obviosuly need to first run this playbook from some other user. We assume your VPS provider has given you a root user, which is what you need to define as the running user in the next command.
|
||||||
* Run `ansible-playbook playbook.yml`
|
* cd into `ansible`
|
||||||
|
* Run `ansible-playbook -i inventory.ini infra/01_user_and_access_setup_playbook.yml -e 'ansible_user="your root user here"'
|
||||||
|
* Then, configure firewall access, fail2ban and auditd with `ansible-playbook -i inventory.ini infra/02_firewall_playbook.yml`
|
||||||
|
|
||||||
|
Note that both the root user and the `counterweight` user will use the same SSH pubkey for auth.
|
||||||
18
02_vps_core_services_setup.md
Normal file
18
02_vps_core_services_setup.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# 02. VPS Core Services Setup
|
||||||
|
|
||||||
|
Now that Vipy is ready, we need to deploy some basic services which are foundational for the apps we're actually interested in.
|
||||||
|
|
||||||
|
This assumes you've completed the markdown `01`.
|
||||||
|
|
||||||
|
## 02.01 Deploy Caddy
|
||||||
|
|
||||||
|
* Use Ansible to run the caddy playbook:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ansible
|
||||||
|
ansible-playbook -i inventory.ini services/caddy_playbook.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
* Starting config will be empty. Modifying the caddy config file to add endpoints as we add services is covered by the instructions of each service.
|
||||||
|
|
||||||
|
## 02.02 Deploy Uptime Kuma
|
||||||
2
ansible/example.inventory.ini
Normal file
2
ansible/example.inventory.ini
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[vipy]
|
||||||
|
your.vps.ip.here ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/your-key
|
||||||
65
ansible/infra/01_user_and_access_setup_playbook.yml
Normal file
65
ansible/infra/01_user_and_access_setup_playbook.yml
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
- name: Secure Debian VPS
|
||||||
|
hosts: vipy
|
||||||
|
vars_files:
|
||||||
|
- ../vars.yml
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update and upgrade apt packages
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
upgrade: full
|
||||||
|
autoremove: yes
|
||||||
|
|
||||||
|
- name: Create new user
|
||||||
|
user:
|
||||||
|
name: "{{ new_user }}"
|
||||||
|
groups: sudo
|
||||||
|
shell: /bin/bash
|
||||||
|
state: present
|
||||||
|
create_home: yes
|
||||||
|
|
||||||
|
- name: Set up SSH directory for new user
|
||||||
|
file:
|
||||||
|
path: "/home/{{ new_user }}/.ssh"
|
||||||
|
state: directory
|
||||||
|
mode: "0700"
|
||||||
|
owner: "{{ new_user }}"
|
||||||
|
group: "{{ new_user }}"
|
||||||
|
|
||||||
|
- name: Copy current user's authorized_keys to new user
|
||||||
|
copy:
|
||||||
|
src: "/home/{{ ansible_user }}/.ssh/authorized_keys"
|
||||||
|
dest: "/home/{{ new_user }}/.ssh/authorized_keys"
|
||||||
|
owner: "{{ new_user }}"
|
||||||
|
group: "{{ new_user }}"
|
||||||
|
mode: "0600"
|
||||||
|
remote_src: true
|
||||||
|
|
||||||
|
- name: Allow new user to run sudo without password
|
||||||
|
copy:
|
||||||
|
dest: "/etc/sudoers.d/{{ new_user }}"
|
||||||
|
content: "{{ new_user }} ALL=(ALL) NOPASSWD:ALL"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0440"
|
||||||
|
|
||||||
|
- name: Disable root login
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: "{{ item.regexp }}"
|
||||||
|
line: "{{ item.line }}"
|
||||||
|
state: present
|
||||||
|
backrefs: yes
|
||||||
|
loop:
|
||||||
|
- { regexp: "^#?PermitRootLogin .*", line: "PermitRootLogin no" }
|
||||||
|
- {
|
||||||
|
regexp: "^#?PasswordAuthentication .*",
|
||||||
|
line: "PasswordAuthentication no",
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Restart SSH
|
||||||
|
service:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
|
@ -1,56 +1,10 @@
|
||||||
- name: Secure Debian VPS
|
- name: Secure Debian VPS
|
||||||
hosts: vipy
|
hosts: vipy
|
||||||
vars_files:
|
vars_files:
|
||||||
- vars.yml
|
- ../vars.yml
|
||||||
become: true
|
become: true
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Update and upgrade apt packages
|
|
||||||
apt:
|
|
||||||
update_cache: yes
|
|
||||||
upgrade: full
|
|
||||||
autoremove: yes
|
|
||||||
|
|
||||||
- name: Create new user
|
|
||||||
user:
|
|
||||||
name: "{{ new_user }}"
|
|
||||||
groups: sudo
|
|
||||||
shell: /bin/bash
|
|
||||||
state: present
|
|
||||||
create_home: yes
|
|
||||||
|
|
||||||
- name: Set up SSH directory for new user
|
|
||||||
file:
|
|
||||||
path: "/home/{{ new_user }}/.ssh"
|
|
||||||
state: directory
|
|
||||||
mode: "0700"
|
|
||||||
owner: "{{ new_user }}"
|
|
||||||
group: "{{ new_user }}"
|
|
||||||
|
|
||||||
- name: Change SSH port and disable root login
|
|
||||||
lineinfile:
|
|
||||||
path: /etc/ssh/sshd_config
|
|
||||||
regexp: "{{ item.regexp }}"
|
|
||||||
line: "{{ item.line }}"
|
|
||||||
state: present
|
|
||||||
backrefs: yes
|
|
||||||
loop:
|
|
||||||
- { regexp: "^#?Port .*", line: "Port {{ ssh_port }}" }
|
|
||||||
- { regexp: "^#?PermitRootLogin .*", line: "PermitRootLogin no" }
|
|
||||||
- {
|
|
||||||
regexp: "^#?PasswordAuthentication .*",
|
|
||||||
line: "PasswordAuthentication no",
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Restart SSH
|
|
||||||
service:
|
|
||||||
name: ssh
|
|
||||||
state: restarted
|
|
||||||
|
|
||||||
- name: Set SSH port to new port
|
|
||||||
set_fact:
|
|
||||||
ansible_port: "{{ ssh_port }}"
|
|
||||||
|
|
||||||
- name: Install UFW
|
- name: Install UFW
|
||||||
apt:
|
apt:
|
||||||
name: ufw
|
name: ufw
|
||||||
|
|
@ -68,11 +22,12 @@
|
||||||
- name: Allow outgoing traffic
|
- name: Allow outgoing traffic
|
||||||
ufw:
|
ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
direction: outgoing
|
direction: out
|
||||||
|
|
||||||
- name: Allow SSH port through UFW
|
- name: Allow SSH port through UFW
|
||||||
ufw:
|
ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
|
direction: in
|
||||||
port: "{{ ssh_port }}"
|
port: "{{ ssh_port }}"
|
||||||
proto: tcp
|
proto: tcp
|
||||||
from_ip: "{{ allow_ssh_from if allow_ssh_from != 'any' else omit }}"
|
from_ip: "{{ allow_ssh_from if allow_ssh_from != 'any' else omit }}"
|
||||||
61
ansible/services/caddy_playbook.yml
Normal file
61
ansible/services/caddy_playbook.yml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
- name: Install and configure Caddy on Debian 12
|
||||||
|
hosts: vipy
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- debian-keyring
|
||||||
|
- debian-archive-keyring
|
||||||
|
- apt-transport-https
|
||||||
|
- curl
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Download Caddy GPG armored key
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://dl.cloudsmith.io/public/caddy/stable/gpg.key
|
||||||
|
dest: /tmp/caddy-stable-archive-keyring.asc
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Convert ASCII armored key to binary keyring
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg /tmp/caddy-stable-archive-keyring.asc
|
||||||
|
args:
|
||||||
|
creates: /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
||||||
|
|
||||||
|
- name: Ensure permissions on keyring file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Add Caddy repository list file
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt
|
||||||
|
dest: /etc/apt/sources.list.d/caddy-stable.list
|
||||||
|
mode: '0644'
|
||||||
|
validate_certs: yes
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Install Caddy
|
||||||
|
apt:
|
||||||
|
name: caddy
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure Caddy service is enabled and started
|
||||||
|
systemd:
|
||||||
|
name: caddy
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Allow HTTPS through UFW
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '443'
|
||||||
|
proto: tcp
|
||||||
59
ansible/services/docker_playbook.yml
Normal file
59
ansible/services/docker_playbook.yml
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
- name: Install Docker and Docker Compose on Debian 12
|
||||||
|
hosts: all
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Ensure required packages are installed
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- lsb-release
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
ansible.builtin.apt_key:
|
||||||
|
url: https://download.docker.com/linux/debian/gpg
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
repo: "deb [arch=amd64] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding Docker repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Install Docker Engine and CLI
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: latest
|
||||||
|
|
||||||
|
- name: Ensure Docker is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Add user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
|
||||||
|
- name: Create symlink for docker-compose (optional CLI alias)
|
||||||
|
file:
|
||||||
|
src: /usr/libexec/docker/cli-plugins/docker-compose
|
||||||
|
dest: /usr/local/bin/docker-compose
|
||||||
|
state: link
|
||||||
|
when: ansible_facts['os_family'] == "Debian"
|
||||||
|
ignore_errors: true # In case the plugin path differs slightly
|
||||||
51
ansible/services/uptime_kuma_playbook.yml
Normal file
51
ansible/services/uptime_kuma_playbook.yml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
- name: Deploy Uptime Kuma with Docker Compose and configure Caddy reverse proxy
|
||||||
|
hosts: vipy
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
uptime_kuma_dir: /opt/uptime-kuma
|
||||||
|
uptime_kuma_port: 3001
|
||||||
|
caddy_sites_dir: /etc/caddy/sites-enabled
|
||||||
|
uptime_kuma_domain: uptime.example.com # Change to your domain
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create uptime kuma directory
|
||||||
|
file:
|
||||||
|
path: "{{ uptime_kuma_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: {{ ansible_user }}
|
||||||
|
group: {{ ansible_user }}
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Create docker-compose.yml for uptime kuma
|
||||||
|
copy:
|
||||||
|
dest: "{{ uptime_kuma_dir }}/docker-compose.yml"
|
||||||
|
content: |
|
||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
uptime-kuma:
|
||||||
|
image: louislam/uptime-kuma:latest
|
||||||
|
container_name: uptime-kuma
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "{{ uptime_kuma_port }}:3001"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
|
||||||
|
- name: Deploy uptime kuma container with docker compose
|
||||||
|
command: docker-compose up -d
|
||||||
|
args:
|
||||||
|
chdir: "{{ uptime_kuma_dir }}"
|
||||||
|
|
||||||
|
- name: Create Caddy reverse proxy configuration for uptime kuma
|
||||||
|
copy:
|
||||||
|
dest: "{{ caddy_sites_dir }}/uptime-kuma.conf"
|
||||||
|
content: |
|
||||||
|
{{ uptime_kuma_domain }} {
|
||||||
|
reverse_proxy localhost:{{ uptime_kuma_port }}
|
||||||
|
}
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Reload Caddy to apply new config
|
||||||
|
command: systemctl reload caddy
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
new_user: counterweight
|
new_user: counterweight
|
||||||
ssh_port: 2222
|
ssh_port: 22
|
||||||
allow_ssh_from: "any"
|
allow_ssh_from: "any"
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[vipy]
|
|
||||||
your.vps.ip.here ansible_user=debian ansible_port=22
|
|
||||||
10
requirements.txt
Normal file
10
requirements.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
ansible==10.7.0
|
||||||
|
ansible-core==2.17.12
|
||||||
|
cffi==1.17.1
|
||||||
|
cryptography==45.0.4
|
||||||
|
Jinja2==3.1.6
|
||||||
|
MarkupSafe==3.0.2
|
||||||
|
packaging==25.0
|
||||||
|
pycparser==2.22
|
||||||
|
PyYAML==6.0.2
|
||||||
|
resolvelib==1.0.1
|
||||||
Loading…
Add table
Add a link
Reference in a new issue