Skip to content

Commit 752abc0

Browse files
committed
Support for encryption, updated README
1 parent 0f8d3e2 commit 752abc0

File tree

7 files changed

+259
-21
lines changed

7 files changed

+259
-21
lines changed

.rkd/makefile.yaml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,30 @@ tasks:
3939
"--role":
4040
help: "Limit to a given role"
4141
required: False
42+
"--host":
43+
help: "Host name or group name"
44+
required: True
45+
"--vault":
46+
help: "Ask for vault passwords"
47+
action: store_true
4248
steps: |
4349
if [[ $ARG_ROLE ]]; then
4450
ARG_ARGS="$ARG_ARGS -t $ARG_ROLE"
4551
fi
4652
47-
ansible-playbook ./playbooks/$ARG_PLAYBOOK -i inventory/hosts.cfg ${ARG_ARGS}
53+
if [[ $ARG_VAULT ]]; then
54+
ARG_ARGS="$ARG_ARGS --ask-vault-pass"
55+
fi
56+
57+
ansible-playbook ./playbooks/$ARG_PLAYBOOK -i inventory/hosts.cfg --limit=${ARG_HOST} ${ARG_ARGS}
4858
59+
60+
:node:encrypt-first-time:
61+
description: Perform a partial disk encryption on freshly installed OS
62+
arguments:
63+
"--args":
64+
help: "Additional Ansible commandline arguments"
65+
required: False
66+
"host":
67+
help: "Host name or group name"
68+
steps: ansible-playbook ./playbooks/encrypt-disks.yml --limit=$ARG_HOST -i inventory/hosts.cfg ${ARG_ARGS}

.templates/inventory/group_vars/all.yaml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,91 @@
11

2+
docker_dependent_services: ['project']
3+
4+
#
5+
# Encryption role settings
6+
#
7+
# instead of overriding hooks override this to adjust hooks
8+
enc_directories_to_map:
9+
- { dst: "/project", name: "project" }
10+
- { dst: "/root", name: "root" }
11+
- { dst: "/var/log", name: "var-log" }
12+
enc_notify_systemd_service: "project"
13+
14+
# https://github.com/zwiazeksyndykalistowpolski/server-secure-storage
15+
default_role_encryption:
16+
enc_file: /storage # path, where all of the data will be stored
17+
enc_file_size: 17160M # examples: 256M, 20G, 500G
18+
enc_mount_name: storage # mount name, should be a-z, lower case, without special letters
19+
enc_mount_path: /mnt/storage # mount path
20+
enc_file_filesystem: ext4 # any filesystem supported by mkfs (and supported by the operating system)
21+
enc_hidden_volume_size: "16900M" # ~17 GB
22+
enc_filesystem_create_if_not_exists: yes
23+
hide_sensitive_output: no
24+
25+
#enc_passphrase: "test123"
26+
#enc_hidden_volume_passphrase: "hidden123"
27+
28+
# tcplay settings
29+
hashing_algorithm: whirlpool
30+
encryption_algorithm: AES-256-XTS
31+
32+
hook_pre_mount: ""
33+
hook_post_mount: >
34+
set -x;
35+
36+
mkdir -p /mnt/storage/docker/volumes /var/lib/docker;
37+
38+
{% for directory in enc_directories_to_map %}
39+
BACKUP=false;
40+
41+
if [[ -d "{{ directory.dst }}" ]]; then
42+
rm -rf "{{ directory.dst }}.2";
43+
mv "{{ directory.dst }}" "{{ directory.dst }}.2";
44+
BACKUP=true;
45+
fi;
46+
47+
mkdir -p "{{ directory.dst }}";
48+
mount -o bind "/mnt/storage/{{ directory.name }}" "{{ directory.dst }}" || exit 1;
49+
50+
if [[ "${BACKUP}" == "true" ]]; then
51+
mv "{{ directory.dst }}.2/*" "{{ directory.dst }}/";
52+
mv "{{ directory.dst }}.2/.*" "{{ directory.dst }}/" || true;
53+
rmdir "{{ directory.dst }}.2" || true;
54+
fi;
55+
{% endfor %}
56+
57+
mount -o bind /mnt/storage/docker /var/lib/docker || exit 1;
58+
mount --bind /var/lib/docker/plugins /var/lib/docker/plugins || true;
59+
mount --make-private /var/lib/docker/plugins || true;
60+
61+
{% if enc_notify_systemd_service %}
62+
if [[ -f /etc/systemd/system/{{ enc_notify_systemd_service }}.service ]]; then
63+
sudo systemctl restart docker;
64+
sleep 5;
65+
sudo systemctl restart project;
66+
fi;
67+
{% endif %}
68+
69+
hook_pre_unmount: >
70+
{% if enc_notify_systemd_service %}
71+
if [[ -f /etc/systemd/system/{{ enc_notify_systemd_service }}.service ]]; then
72+
sudo systemctl disable docker;
73+
sudo systemctl disable project;
74+
75+
sudo systemctl stop project;
76+
sudo systemctl stop docker;
77+
fi;
78+
{% endif %}
79+
80+
umount /var/lib/docker/plugins || true;
81+
umount /var/lib/docker || true;
82+
83+
{% for directory in enc_directories_to_map %}
84+
umount "{{ directory.dst }}" || true;
85+
{% endfor %}
86+
87+
hook_post_unmount: ""
88+
289
# https://github.com/zwiazeksyndykalistowpolski/server-multi-user
390
default_role_users:
491
technical_entrypoint: "/project/make.sh"

README.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
RiotKit Universal Node
22
======================
33

4-
Turns a typical cheap virtual node into a dockerized applications environment. Natively integrates with RiotKit's Harbor 2+ for webservices deployment.
4+
Turns a typical cheap virtual node into a dockerized applications environment node. Natively integrates with RiotKit's Harbor 2+ for webservices deployment.
5+
6+
Installs docker, docker-compose, adds users, configures logs rotation, configures security.
57

68
First time setup
79
----------------
810

911
```bash
12+
# setup a repository
13+
git clone git@github.com:riotkit-org/infrastructure-harbor-universal-node.git
14+
15+
cd infrastructure-harbor-universal-node
16+
$(./setup-venv.sh)
17+
18+
# set INVENTORY_GIT_URL to a URL of your repository that contains Ansible inventory with hosts.cfg, host_vars/, group_vars/
1019
cp .env-dist .env
1120
nano .env
1221

@@ -35,3 +44,76 @@ This set of playbooks needs to run at least on this specification:
3544
- HDD: 20-40 GB SSD (including OS)
3645
- OS: Ubuntu 16.04+ or latest Debian Stable or Latest Armbian
3746
- Host type: Physical ARM or KVM
47+
48+
Usage documentation
49+
===================
50+
51+
Operating
52+
---------
53+
54+
Each operation is performed using RKD (RiotKit-Do) using `rkd` command.
55+
It is recommended to work in a virtual env using `$(./setup-venv.sh)` wrapper - for stability and reproducibility.
56+
57+
Design - concept
58+
----------------
59+
60+
The architecture requires that the Ansible Inventory (list of SSH hosts with variables per host to customize deployment roles) should be placed
61+
in a separate repository, and the url should be in `.env` at `INVENTORY_GIT_URL` variable.
62+
63+
Thanks to this concept we can leave this *Universal Node Repository* at github, and all the secrets and personalized settings
64+
have separated in other, private repository - to update *Universal Node Repository* we can just do `git pull`. It can be also forked
65+
into private repository for full customization.
66+
67+
How to create inventory repository?
68+
-----------------------------------
69+
70+
Inventory structure should consist of:
71+
72+
**hosts.cfg (example)**
73+
74+
```bash
75+
[disasterrecovery]
76+
recovery.example.internal
77+
78+
```
79+
80+
**group_vars/all**
81+
82+
This file should be actually created from template by executing command `rkd :copy-host-defaults` first time.
83+
In it you can define deployment settings globally for EACH HOST.
84+
85+
**host_vars/recovery.example.internal.yaml (example name)**
86+
87+
There you should define `ansible_ssh_user`, `ansible_ssh_pass`, `ansible_sudo_pass` and/or private key path.
88+
In this file you can also overwrite deployment settings for this host.
89+
90+
When in `group_vars/all` there is a section for example `default_role_encryption` then you can create a `role_encryption` in `host_vars/recovery.example.internal.yaml`.
91+
The values will be MERGED together, the section would not replace original one but will merge all values recursively.
92+
93+
**ENCRYPTION**
94+
95+
Each host file in host_vars can be encrypted with a different Ansible Vault key, Ansible supports this.
96+
With this combination you can divide access to multiple admins handling administration of different servers.
97+
98+
*TIP: Keep hosts.cfg with minimum of information (only group names and host names) to keep it unencrypted, so you will not have to enter password twice*
99+
100+
**Adding this inventory repository**
101+
102+
```bash
103+
# set url in INVENTORY_GIT_URL
104+
nano .env
105+
```
106+
107+
Deploying
108+
---------
109+
110+
```bash
111+
# perform a partial disk encryption (optional)
112+
rkd :encrypt-first-time recovery.example.internal
113+
114+
# provision with users, firewall settings, etc. - a regular deployment
115+
rkd :deploy prepare-machine.yml --host recovery.example.internal --vault
116+
117+
# update operating system with careful
118+
rkd :deploy update-machines.yml --host recovery.example.internal --vault
119+
```

playbooks/encrypt-disks.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# ENCRYPTION PLAYBOOK
3+
# ===================
4+
# Setup an optional partial disk encryption.
5+
# WARNING: Make a backup of target folders that would be mounted, there is a high risk of loosing data when setting up
6+
# a fresh encryption.
7+
#
8+
9+
10+
- hosts: all
11+
gather_facts: no
12+
roles:
13+
- role: blackandred.server_ssh_fallback_port
14+
when: ssh_fallback_port is defined and ssh_fallback_port > 0
15+
vars:
16+
fallback_ssh_port: "{{ ssh_fallback_port }}"
17+
18+
19+
- hosts: all
20+
gather_facts: yes
21+
tasks:
22+
- name: Encryption role
23+
when: role_encryption is defined
24+
block:
25+
- name: Include required vars
26+
set_fact:
27+
args: "{{ default_role_encryption | combine(role_encryption | default({}), recursive=True) }}"
28+
29+
- include_role: name=blackandred.server_secure_storage
30+
tags: encryption

playbooks/prepare-machine.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
#
2+
# PREPARE MACHINES PLAYBOOK
3+
# =========================
4+
# Prepares a complete setup for each machine - including users, firewall, docker, journald
5+
#
6+
7+
18
#
29
# Make sure we still know the port, even when we changed the port for security reasons on previous runs
310
#

playbooks/update-machines.yml

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# UPDATE MACHINE PLAYBOOK
2+
# UPDATE MACHINES PLAYBOOK
33
# =======================
44
# Performs packages upgrade on target machine. Considers a fact that docker daemon could be corrupted after update
55
# and will attempt to restart it with all dependent services
@@ -41,22 +41,34 @@
4141
shell: "dpkg -s docker-ce | grep -i version | awk '{print $2}'"
4242
register: docker_version_after
4343

44-
- name: Stop dependent services
45-
become: yes
46-
systemd:
47-
name: "{{ item }}"
48-
state: stopped
49-
with_items: "{{ docker_dependent_services }}"
44+
- set_fact:
45+
should_rescue_services_after_docker_update: "{{ docker_version_after.stdout != docker_version_before.stdout }}"
5046

51-
- name: Restart docker daemon
52-
become: yes
53-
systemd:
54-
name: docker
55-
state: restarted
47+
- debug:
48+
var: docker_version_after
5649

57-
- name: Bring dependent services back
58-
become: yes
59-
systemd:
60-
name: "{{ item }}"
61-
state: started
62-
with_items: "{{ docker_dependent_services }}"
50+
- debug:
51+
var: docker_version_before
52+
53+
- name: Rescue
54+
when: should_rescue_services_after_docker_update
55+
block:
56+
- name: Stop dependent services
57+
become: yes
58+
systemd:
59+
name: "{{ item }}"
60+
state: stopped
61+
with_items: "{{ docker_dependent_services }}"
62+
63+
- name: Restart docker daemon
64+
become: yes
65+
systemd:
66+
name: docker
67+
state: restarted
68+
69+
- name: Bring dependent services back
70+
become: yes
71+
systemd:
72+
name: "{{ item }}"
73+
state: started
74+
with_items: "{{ docker_dependent_services }}"

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
rkd==2.1.4
1+
rkd>=2.1.4, <2.2

0 commit comments

Comments
 (0)