Compare commits

...

87 Commits

Author SHA1 Message Date
4a516eee15 Stop assuming rockylinux has firewalld installed by default 2023-05-19 16:39:52 -04:00
15a1411f1a Add project resource assignments 2023-05-07 16:16:03 -04:00
868ab721dd Add scipio project 2023-05-07 16:06:53 -04:00
9776e9a316 Add skylab project definition 2023-05-07 16:04:25 -04:00
28f1f80d6f Remove pdb.enp.one 2023-05-07 15:49:14 -04:00
0f9479731a Update domains to use pointer vars instead of repeat values 2023-05-07 15:48:29 -04:00
3df0115191 Add CDN config for space 2023-05-07 15:43:39 -04:00
fcb25b79ce Add CDN space 2023-05-07 14:59:17 -04:00
e591db8581 Add auth subdomain 2023-05-04 16:23:59 -04:00
e4fd90c013 Restructure en1 main inventory group 2023-05-02 22:44:27 -04:00
219b03b4ee Add notify subdomain for scipio app 2023-05-02 22:44:26 -04:00
1b941a11a2 Add docs and notify subdomains to scipio doman 2023-05-02 18:02:20 -04:00
12991700b9 Disable hostkey checking on connection test task 2023-04-21 20:59:57 -04:00
02b6460cff Add ssh port update to bootstrap playbook
Update to use dynamic managment settings
Remove check for existing bootstrap directory
Fix re-using ansible password for root user
2023-04-19 18:42:04 -04:00
5f602c797f Add sanity connection check for bootstrap hosts 2023-04-18 21:56:02 -04:00
538bb26f83 Fix updating ssh keys before user exists 2023-04-18 21:39:32 -04:00
fa0df823ee Add main hosts for scipio domain 2023-04-14 15:11:45 -04:00
49eacf103c Add scipiocapital domain 2023-04-13 23:35:02 -04:00
4d1d28c64b Add pdb subdomain for grist 2023-04-11 17:49:33 -04:00
5803ea337e Add www subdomain for enp 2023-04-05 23:04:34 -04:00
20e9ec68d2 Improve docs on cloud playbook 2023-04-05 01:52:45 -04:00
d901c1d940 Add cloud deployment playbook for terraform operations 2023-04-05 01:39:25 -04:00
875d8f1538 Move terraform files to infra collection 2023-04-05 01:38:55 -04:00
1e1677cb4d Add terraform format precommit
Format terraform files
2023-04-04 16:54:01 -04:00
29bccbac02 Add img service cname 2023-04-04 16:47:22 -04:00
80015c6535 Add terraform proof of concept for DO domain management 2023-04-04 13:17:02 -04:00
3bcbee1b85 Update infra role meta to remove boilerplate 2023-04-04 12:20:37 -04:00
8f965c3e2b Restructure inventory for updated deployment schemas 2023-04-01 22:01:55 -04:00
88247b4011 Finalize and debug bootstrap playbook 2023-04-01 22:01:29 -04:00
740b73cb7d Update default to always prompt for vault password 2023-03-31 12:19:50 -04:00
857e83a6fe Add wip bootstrap playbook 2023-03-19 03:12:54 -04:00
745f6acc04 Add new infra collection 2023-03-19 01:45:43 -04:00
43fbb3993b Update makefile to use latest poetry command syntax 2023-03-19 01:45:23 -04:00
955d7e8a64 Enable hostkey checking and disable default forwarding 2023-03-19 01:35:47 -04:00
614fca41c0 Update with latest practices 2023-03-19 01:35:30 -04:00
0163d5ab18 Update transient deps 2023-03-19 01:15:18 -04:00
eb2ad9e60a Add task to link external media mount dir into user home directory 2022-07-11 01:12:31 -04:00
11235ab859 Fix typo in bashrc for setting ansible path 2022-05-24 23:22:19 -04:00
ce72850721 Change projects dir to home dir 2022-05-24 23:11:37 -04:00
d5f92811bd Add loading of local profile bash completions 2022-05-24 22:33:59 -04:00
2d26caba54 Fix typo in gg completions 2022-05-24 22:29:58 -04:00
36ce40d718 Fix wallpaper install task 2022-05-20 17:09:57 -04:00
a7d9e1b270 Add wallpaper for voyager workstation 2022-05-20 17:07:03 -04:00
a6d1d46236 Add fedora to list of supported OS's 2022-05-20 17:06:21 -04:00
d9c00a0d9e Fix user variable usage in completions task 2022-05-20 17:05:12 -04:00
f3008294e4 Add ansible project support to gg function 2022-05-20 17:04:50 -04:00
58dcf4694f Add voyager workstation to inventory 2022-05-20 16:57:50 -04:00
a822fe0915 Add completions integration to workstation env 2022-05-20 16:55:44 -04:00
cd1910c2bd Update SSH keys 2022-05-20 16:41:26 -04:00
421ceabd9e Add arc-theme to list of workstation packages
Whooo first commit from voyager!
2022-05-20 16:36:57 -04:00
068a33626d Add initial structure for workstation role 2022-05-16 21:57:31 -04:00
8b4fb71160 Add support for fedora workstations in core tooling 2022-05-16 21:57:12 -04:00
72d8e7cdde Add meta support for fedora 2022-04-25 21:10:07 -04:00
58128eec46 Add workstation target to ansible and enpaul users 2022-04-25 20:26:20 -04:00
48e7b8208e Add pingtest script for corona network monitor 2022-04-09 01:55:46 -04:00
1c417eda10 Add tox for static checks
Add toxdir to gitignore
Add ansible and yamllint
2022-01-08 22:16:40 -05:00
14ce2dfea6 Replace ansible dep with ansible-core
Add collection dependencies
2022-01-08 21:56:11 -05:00
e9974a054e Update swarm join timeout from 5min to 20min 2022-01-08 21:34:41 -05:00
f61baa3f04 Consolidate ansible settings into config file
Update docs
2021-12-28 00:27:46 -05:00
46e1366c4f Update service config spec to include published resources 2021-12-23 23:36:13 -05:00
924341a276 Update documentation 2021-12-23 23:27:00 -05:00
b36bbec72a Replace hacky ansible entrypoint script with dotenv file 2021-12-23 23:25:40 -05:00
7bb00a3586 Add environment check to collection linking script 2021-12-23 23:25:40 -05:00
9cd0cfcb4f Fix playbook import syntax 2021-12-21 17:45:01 -05:00
80c3565fa1 Update ansible script to use local collections path 2021-12-20 18:44:48 -05:00
fe0fc835cd Add logic for building local ansible 'virtualenv'
Add makefile and targets for building local dev environment
Add script for linking dev collections into local collection dir
Add local collection dir to gitignore
2021-12-20 18:44:48 -05:00
ed2fd510a5 Rename requirements file to keep consistent file ext 2021-12-20 18:34:45 -05:00
b3e2d1c887 Add community.docker collection dependency 2021-12-20 18:12:51 -05:00
6afb84b443 Add collection namespacing to playbook roles 2021-12-11 22:41:11 -05:00
5ead10afb9 Fix node ip presence check defaulting to /32 addresses
Fix typo in task name
2021-12-11 17:35:59 -05:00
4e1d50504d Rename playbooks to use _ instead of - for new collection structure 2021-12-11 16:58:36 -05:00
50e161f8dc Add 5min timeout to swarm join operation 2021-12-11 16:44:27 -05:00
3001e19c7e Restructore project into collection 2021-12-11 15:59:09 -05:00
85877f8431 Bump ansible to ^4.9 2021-12-11 15:59:09 -05:00
425761f0f5 Fix incorrect netdev type key name 2021-12-11 15:59:09 -05:00
1e0eb9b426 Add missing datastore config for pegasus 2021-12-11 15:59:08 -05:00
f791b43c86 Update nat rule number for adguard server 2021-12-11 15:59:08 -05:00
12ceb3558b Add bootstrap tasks to node up/down playbooks 2021-12-11 15:59:08 -05:00
eb1ff31e30 Add initial nginx config to deployment playbook 2021-12-11 15:59:08 -05:00
d611301f8a Add initial (incomplete) stack deployment playbook 2021-12-11 15:59:08 -05:00
03574c1560 Fix misnamed automation account for minecraft user 2021-12-11 15:59:08 -05:00
ea2f797b30 Fix invalid service name for _meta 2021-12-11 15:59:08 -05:00
687e189b18 Add initial config for dedicated monitoring server 2021-11-16 23:21:23 -05:00
37b22c7ef5 Add full FQDN to iridium 2021-11-16 23:21:23 -05:00
cf22d27c57 Remove hacky and frankly embarassing role usage pattern 2021-11-15 20:56:02 -05:00
b4feffc118 Fix backwards y in server motd 2021-11-15 19:59:34 -05:00
0c95df3066 Update access targets to be optional parameter
Add server role to iridium
2021-11-15 19:53:19 -05:00
119 changed files with 5756 additions and 995 deletions

9
.ansible-lint.yaml Normal file
View File

@@ -0,0 +1,9 @@
---
skip_list:
- line-length # don't yell about line length
- meta-no-info # we don't publish to galaxy so stop yelling about it
- package-latest # we install lots of latest stuff still 😢
- experimental # no instability plz, give us a call when ur stable
warn_list:
- no-handler # good to keep, but shouldn't be fatal

4
.gitignore vendored
View File

@@ -5,3 +5,7 @@ playbooks/testing.yml
*.idea *.idea
**/__pycache__/ **/__pycache__/
.venv/ .venv/
.ansible/
.tox/
.terraform/
.terraform.lock.*

View File

@@ -32,3 +32,11 @@ repos:
- "--wrap=90" - "--wrap=90"
types: types:
- markdown - markdown
- id: terraform
name: terraform format
entry: terraform
language: system
args:
- fmt
files: ".*\\.tf$"

7
.yamllintrc.yaml Normal file
View File

@@ -0,0 +1,7 @@
---
yaml-files:
- "*.yml"
- "*.yaml"
rules:
line-length: disable

9
Makefile Normal file
View File

@@ -0,0 +1,9 @@
clean:
rm --recursive --force .ansible/
rm --recursive --force .tox/
dev:
@poetry install --sync
@poetry run pre-commit install
@poetry run ansible-galaxy collection install --requirements-file ./requirements.yaml --collections-path ./.ansible
@bash ./link-local-collections.sh

View File

@@ -2,13 +2,17 @@
Ansible configs for the Skylab Homelab Ansible configs for the Skylab Homelab
Main entrypoint is through the `ansible` script in this repository. The script sets up ## Local workstation setup:
basic environment variables to avoid conflicts with other environments and sets the
inventory.
Bootstrap checklist: ```bash
make dev
poetry run ansible-playbook ...
```
1. Install a supported operating system: [Rocky Linux](https://rockylinux.org) ## Boostraping remote system for management:
1. Install a supported operating system: [Rocky Linux](https://rockylinux.org),
[Fedora](https://getfedora.org)
2. During installation create a user named `ansible` with any password 2. During installation create a user named `ansible` with any password
3. After installation copy SSH key to the `ansible` user 3. After installation copy SSH key to the `ansible` user
4. Enable password-less sudo access for the `ansible` user with this command: 4. Enable password-less sudo access for the `ansible` user with this command:

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
ANSIBLE_LIBRARY='' \
ANSIBLE_FILTER_PLUGINS='' \
ANSIBLE_CONFIG='' \
ANSIBLE_INVENTORY=$(pwd)/inventory.yaml \
"ansible-$1" ${@:2}

View File

@@ -1,8 +1,10 @@
[defaults] [defaults]
host_key_checking = false host_key_checking = true
collections_path = .ansible
inventory = inventory/
[ssh_connection] [ssh_connection]
ssh_args = "-o ControlMaster=auto -o ControlPersist=60s -o ForwardAgent=yes" ssh_args = "-o ControlMaster=auto -o ControlPersist=60s"
[inventory] [inventory]
enable_plugins = ansible.builtin.yaml enable_plugins = ansible.builtin.yaml

View File

@@ -1,17 +1,17 @@
--- ---
all: workstation:
vars: hosts:
skylab_state_dir: /var/lib/skylab voyager:
skylab_ansible_venv: "{{ skylab_state_dir }}/ansible-runtime" skylab_description: Personal Workstation
skylab_pip_version: 19.3.1 skylab_hostname: voyager.skylab.enp.one
ansible_user: ansible skylab_targets: [workstation]
ansible_ssh_common_args: "-o ControlMaster=auto -o ControlPersist=60s -o ForwardAgent=yes"
en1: en1:
vars: vars:
skylab_location: Newton MA skylab_location: Newton MA
skylab_dashboard: info.en1.local
# gross hack for now, will be refactored later # gross hack for now, will be refactored later
_skylab_adguard_nat_rule: 8 _skylab_adguard_nat_rule: 9
hosts: hosts:
core: core:
@@ -23,7 +23,17 @@ en1:
iridium: iridium:
ansible_host: 10.42.101.200 ansible_host: 10.42.101.200
skylab_description: Local Monitor Node skylab_description: Local Monitor Node
skylab_hostname: iridium.skylab.enp.one
skylab_targets: [network] skylab_targets: [network]
skylab_networking:
enp4s0:
firewall: internal
dhcp: false
gateway: 10.42.101.1/24
dns:
- 10.42.101.1
addresses:
- 10.42.101.200/24
children: children:
@@ -31,10 +41,7 @@ en1:
vars: vars:
skylab_targets: [cluster, datastore] skylab_targets: [cluster, datastore]
skylab_compose_version: 3.8 skylab_compose_version: 3.8
skylab_roles: skylab_compose_dir: "{{ skylab_state_dir }}/compose"
- server
- datastore
- swarm
hosts: hosts:
pegasus: # jupiter pegasus: # jupiter
@@ -51,13 +58,14 @@ en1:
interface: interface:
access: bond0 access: bond0
internal: bond0.99 internal: bond0.99
skylab_datastore_device: sdb
skylab_networking: skylab_networking:
eno1: eno1:
bond: bond0 bond: bond0
eno2: eno2:
bond: bond0 bond: bond0
bond0: bond0:
type: bond device: bond
firewall: internal firewall: internal
gateway: 10.42.101.1/24 gateway: 10.42.101.1/24
dns: dns:
@@ -67,7 +75,7 @@ en1:
- 192.168.255.255/32 - 192.168.255.255/32
dhcp: false dhcp: false
bond0.99: bond0.99:
type: vlan device: vlan
firewall: trusted firewall: trusted
addresses: addresses:
- 192.168.42.10/24 - 192.168.42.10/24
@@ -93,7 +101,7 @@ en1:
eno2: eno2:
bond: bond0 bond: bond0
bond0: bond0:
type: bond device: bond
firewall: internal firewall: internal
dhcp: false dhcp: false
gateway: 10.42.101.1/24 gateway: 10.42.101.1/24
@@ -103,7 +111,7 @@ en1:
dns: dns:
- 10.42.101.1 - 10.42.101.1
bond0.99: bond0.99:
type: vlan device: vlan
firewall: trusted firewall: trusted
dhcp: false dhcp: false
addresses: addresses:
@@ -130,7 +138,7 @@ en1:
eno2: eno2:
bond: bond0 bond: bond0
bond0: bond0:
type: bond device: bond
firewall: internal firewall: internal
gateway: 10.42.101.1/24 gateway: 10.42.101.1/24
dns: dns:
@@ -140,7 +148,7 @@ en1:
- 192.168.255.255/32 - 192.168.255.255/32
dhcp: false dhcp: false
bond0.99: bond0.99:
type: vlan device: vlan
firewall: trusted firewall: trusted
addresses: addresses:
- 192.168.42.30/24 - 192.168.42.30/24
@@ -156,4 +164,3 @@ en2:
skylab_hostname: hubble.en2.enp.one skylab_hostname: hubble.en2.enp.one
skylab_description: Cloud Web Server skylab_description: Cloud Web Server
skylab_targets: [cloud] skylab_targets: [cloud]
skylab_roles: [server]

51
inventory/en1.yaml Normal file
View File

@@ -0,0 +1,51 @@
---
en1:
vars:
skylab_location: Cambridge
children:
domain:
children:
cluster:
hosts:
canaveral:
ansible_host: 10.42.101.10
skylab_description: Compute and Storage Node
baikonur:
ansible_host: 10.42.101.11
skylab_description: Compute and Storage Node
vandenberg:
ansible_host: 10.42.101.12
skylab_description: Compute and Storage Node
andoya:
ansible_host: 10.42.101.13
skylab_description: Auxilary Compute Node
jiuquan:
ansible_host: 10.42.101.14
skylab_description: Auxilary Compute Node
datastore:
hosts:
canaveral:
skylab_datastore_block: /dev/sda
baikonur:
skylab_datastore_block: /dev/sda
vandenberg:
skylab_datastore_block: /dev/sda
hosts:
3d-printer: {}
mediastore: {}
backstore: {}
local:
hosts:
core: {}
switch-1: {}
switch-2: {}
wap-1: {}
wap-2: {}
wap-3: {}
printer: {}

View File

@@ -0,0 +1,39 @@
---
ansible_user: ansible
ansible_port: 4242
skylab_state_dir: /var/lib/skylab
skylab_ansible_venv: "{{ skylab_state_dir }}/ansible-runtime"
skylab_ansible_vault_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
61323762623165383963316238343539346336663864366631616339356564346636373561616237
6666363531393234636337656431366365343236346536320a346163353935366636303131313661
32623635363063383039363539303135393838376264356463646465376435616363376163373663
6366633665373939380a373234633365376632376433643034336539346338613566353537663731
34323464633165626133306464363464333539363761343831316565356266373833
skylab_tfstate_backend:
hostname: cluster.lab.enp.one
username: terraform
schema: terraform
port: 32421
password: !vault |
$ANSIBLE_VAULT;1.1;AES256
30313365393065316563323363663135313438616461356439366632303636343735653033363930
6334613931376566363064663539643639326363663933610a306138616362376435386466306538
30626330613932363339363438356430613461313335333536623931343436353330393433373630
3631343463616631380a386661336534663033383637666538316665303962353034376232356235
65323339353563623431666535366465353133343137653232326534326436323661636536373564
3466633762303966366366653531613261336561356531636461
skylab_mgmt:
sshport: 4242
group: skylab
user: ansible
id: 1400
sshkeys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP5TGKururOa1Y+cbv8AWXYI5zhfZCDV0fsBG+33IYUc enpaul@ansible.voyager
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBf7i/8hSJDYnoD95noCJJVtSxxCp9N5EmnshALufiwm enpaul@ansible.opportunity

28
link-local-collections.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
PWD=$(pwd)
ANSIBLE_NAMESPACE="skylab"
ANSIBLE_COLLECTION_DIR="$PWD/.ansible/ansible_collections"
mkdir --parents "$ANSIBLE_COLLECTION_DIR/$ANSIBLE_NAMESPACE"
for collection_path in "$PWD"/"$ANSIBLE_NAMESPACE"/*; do
collection=$(basename "$collection_path")
if [[ ! -L "$ANSIBLE_COLLECTION_DIR/$ANSIBLE_NAMESPACE/$collection" ]]; then
echo "Linking $ANSIBLE_NAMESPACE.$collection into $ANSIBLE_COLLECTION_DIR"
rm --recursive --force "${ANSIBLE_COLLECTION_DIR:?}/$ANSIBLE_NAMESPACE/$collection"
ln --symbolic "$PWD/$ANSIBLE_NAMESPACE/$collection" "$ANSIBLE_COLLECTION_DIR/$ANSIBLE_NAMESPACE/$collection"
fi
done
echo "Finished linking local collections"
LOCAL_COLLECTION_PATH=$(dirname "$ANSIBLE_COLLECTION_DIR")
if [ -z ${ANSIBLE_COLLECTIONS_PATH+x} ]; then
echo "WARNING: Environment variable ANSIBLE_COLLECTIONS_PATH is not set, collections will not be callable"
echo " HINT: export ANSIBLE_COLLECTIONS_PATH=$LOCAL_COLLECTION_PATH"
elif [[ ${ANSIBLE_COLLECTIONS_PATH} != *"$LOCAL_COLLECTION_PATH"* ]]; then
echo "WARNING: Environment variable ANSIBLE_COLLECTIONS_PATH does not include local collection directory"
echo " HINT: export ANSIBLE_COLLECTIONS_PATH=\$ANSIBLE_COLLECTIONS_PATH:$LOCAL_COLLECTION_PATH"
fi

View File

@@ -1,28 +0,0 @@
---
- name: Group hosts by platform
hosts: all
tags:
- always
pre_tasks:
- include_tasks: tasks/meta/runtime-group-determination.yaml
- name: Bootstrap remote ansible environment
hosts: linux
gather_facts: false
tags:
- always
tasks:
- include_tasks: tasks/meta/bootstrap-remote-env.yaml
- name: Configure hosts by role
hosts: linux
gather_facts: false
roles:
- role: server
when: "'server' in skylab_roles | default([])"
- role: datastore
when: "'datastore' in skylab_roles | default([])"
- role: swarm
when: "'swarm' in skylab_roles | default([])"

View File

@@ -1 +0,0 @@
../resources

View File

@@ -1 +0,0 @@
../roles

View File

@@ -1 +0,0 @@
../tasks

View File

@@ -1 +0,0 @@
../resources

View File

@@ -1 +0,0 @@
../vars/

2628
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,22 +6,22 @@ authors = ["Ethan Paul <me@enp.one>"]
license = "MIT" license = "MIT"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.8" python = "^3.10"
ansible = "^3.4.0" ansible-core = "^2.14.3"
docker = "^4.2.0" docker = "^6.0.1"
docker-compose = "^1.25.4"
paramiko = "^2.7.1" paramiko = "^2.7.1"
jsondiff = "^1.2.0" jsondiff = "^2.0.0"
netaddr = "^0.8.0" netaddr = "^0.8.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
ansible-lint = "^4.2.0" ansible-lint = {version = "^6.14.0", markers = "platform_system != 'Windows'"}
pre-commit = "^2.9.2" ipython = "^8.11.0"
pre-commit-hooks = "^3.3.0" mdformat = "^0.7.16"
safety = "^1.9.0" mdformat-gfm = "^0.3.5"
poetry = "^1.3.0"
pre-commit = "^3.2.0"
pre-commit-hooks = "^4.4.0"
safety = "^2.3.5"
tox = "^3.20.1" tox = "^3.20.1"
tox-poetry-installer = "^0.8.1" tox-poetry-installer = {extras = ["poetry"], version = "^0.10.0"}
yamllint = "^1.20.0" yamllint = "^1.29.0"
mdformat = "^0.7.9"
mdformat-gfm = "^0.3.3"
ipython = "^7.28.0"

4
requirements.yaml Normal file
View File

@@ -0,0 +1,4 @@
---
collections:
- source: ./skylab/
type: subdirs

View File

@@ -1,11 +0,0 @@
/####### /## /## /## /## /## /####### /#####
/## /##___/## /##__/## /## /##___/## /##__/##
/##____ /####### /###### /## /######## /######
######## /## |## /## /## /## /## /##__/##
/## /## |## \### /## /## /## /######
____/## /##_____
/###### ```````````````````` /######## ``````````````
✨ {{ skylab_description }} @{{ skylab_location }}
{{ ' ' }}

3
skylab/core/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Ansible Collection - skylab.core
Documentation for the collection.

26
skylab/core/galaxy.yml Normal file
View File

@@ -0,0 +1,26 @@
---
namespace: skylab
name: core
version: 0.0.0
description: Network deployment procedures and configuration state management
authors:
- Ethan Paul <me@enp.one>
license:
- MIT
readme: README.md
tags: []
repository: https://vcs.enp.one/skylab/skylab-ansible/
build_ignore: []
# Collections that this collection requires to be installed for it to be usable. The key of the dict is the
# collection label 'namespace.name'. The value is a version range
# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version
# range specifiers can be set and are separated by ','
dependencies:
ansible.netcommon: ">=2.5.0,<3.0.0"
ansible.posix: ">=1.3.0,<2.0.0"
ansible.utils: ">=2.4.3,<3.0.0"
community.docker: ">=2.0.2,<3.0.0"
community.network: ">=3.0.0,<4.0.0"
community.general: ">=4.1.0,<5.0.0"
community.crypto: ">=1.0.0,<2.0.0"

View File

@@ -0,0 +1,2 @@
---
requires_ansible: ">=2.11,<2.15"

View File

@@ -0,0 +1,47 @@
---
- name: Group hosts by platform
hosts: all
tags:
- always
pre_tasks:
- include_tasks: tasks/meta/runtime-group-determination.yaml
- name: Bootstrap remote ansible environment
hosts: linux
gather_facts: false
tags:
- always
tasks:
- include_tasks: tasks/meta/bootstrap-remote-env.yaml
# [lemony snicket voice] "server" here being a word used to mean "not a workstation"
- name: Configure servers
hosts: linux:!workstation
gather_facts: false
roles:
- role: skylab.core.server
- name: Configure cluster
hosts: linux:&cluster
gather_facts: false
roles:
- role: skylab.core.datastore
- role: skylab.core.swarm
- name: Configure dashboard nodes
hosts: iridium
gather_facts: false
roles:
- role: skylab.core.dashboard
dashboard_hostname: "{{ skylab_dashboard }}"
- name: Configure workstations
hosts: workstation
gather_facts: false
roles:
- role: skylab.core.workstation

View File

@@ -0,0 +1,200 @@
---
- name: Bootstrap remote ansible environment
hosts: linux
tags:
- always
tasks:
- include_tasks: tasks/meta/bootstrap-remote-env.yaml
- name: Clean up old orechestration data
hosts: cluster
gather_facts: false
tags:
- cleanup
vars_files:
- vars/services.yaml
- vars/access.yaml
tasks:
- name: Create compose storage directory
become: true
ansible.builtin.file:
path: "{{ skylab_compose_dir }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0770
- name: Fetch existing compose files
ansible.builtin.command:
cmd: /usr/bin/ls {{ skylab_compose_dir }}
changed_when: false
register: _compose_contents_raw
- name: Remove legacy compose files
when: item.replace('.yaml', '') not in skylab_services
ansible.builtin.file:
path: "{{ skylab_compose_dir }}/{{ item }}"
state: absent
loop: "{{ _compose_contents_raw.stdout_lines }}"
- name: Fetch existing stacks
vars:
ansible_python_interpreter: "{{ skylab_ansible_venv }}/bin/python"
community.docker.docker_stack_info: {}
register: _stack_info
- name: Remove legacy stacks
vars:
ansible_python_interpreter: "{{ skylab_ansible_venv }}/bin/python"
when: item.Orchestrator == 'Swarm' and item.Name not in skylab_services
community.docker.docker_stack:
name: "{{ item.Name }}"
state: absent
loop: "{{ _stack_info.results }}"
loop_control:
label: "{{ item.Name }}"
- name: Fetch existing Nginx configs
ansible.builtin.command:
cmd: ls {{ local_datastore_mount }}/appdata/nginx/conf.d/
changed_when: false
register: _nginx_configs
- name: Remove legacy nginx configs
when: item.replace('.conf', '') not in skylab_services
ansible.builtin.file:
path: "{{ local_datastore_mount }}/appdata/nginx/conf.d/{{ item }}.conf"
state: absent
loop: "{{ _nginx_configs.stdout_lines }}"
- name: Deploy stack service{{ (' ' + service) if service is defined else 's' }}
hosts: cluster
gather_facts: false
vars:
local_datastore_mount: /mnt/datastore
vars_files:
- vars/access.yaml
- vars/services.yaml
tasks:
- name: Validate user input
when: service is defined
ansible.builtin.assert:
that:
- service in skylab_services
- name: Determine service stacks to deploy
ansible.builtin.set_fact:
_services: "{{ {service: skylab_services[service]} if service is defined else skylab_services }}"
- name: Determine app account mapping
vars:
_service_accounts: {}
when: item.service | default(false)
ansible.builtin.set_fact:
_service_accounts: "{{ _service_accounts | combine({item.name: item}) }}"
loop: "{{ skylab_accounts }}"
loop_control:
label: "{{ item.name }}"
- name: Create compose directory
become: true
ansible.builtin.file:
path: "{{ skylab_compose_dir }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0770
- name: Install compose file
vars:
app: "{{ item.value }}"
_app_account: "{{ _service_accounts[item.value.user] if item.value.user is defined else false }}"
ansible.builtin.template:
src: docker-compose/{{ item.key }}.yaml.j2
dest: "{{ skylab_compose_dir }}/{{ item.key }}.yaml"
owner: "{{ ansible_user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0660
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Create automation groups
become: true
when: item.value.user is defined
ansible.builtin.group:
name: "{{ item.value.user }}"
gid: "{{ _service_accounts[item.value.user].uid }}"
state: present
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Create automation accounts
become: true
when: item.value.user is defined
ansible.builtin.user:
name: "{{ item.value.user }}"
state: present
uid: "{{ _service_accounts[item.value.user].uid }}"
group: "{{ item.value.user }}"
groups: "{{ [skylab_group_automation.name, skylab_group.name] }}"
system: true
generate_ssh_key: false
password: "{{ _service_accounts[item.value.user].password }}"
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Configure datastore directories
run_once: true
block:
- name: Determine volume directories
vars:
_stack_volume_directories: []
when: item.value.volumes is defined
ansible.builtin.set_fact:
_stack_volume_directories: "{{ _stack_volume_directories + [{'user': (item.value.user | default(ansible_user)), 'volumes': (item.value.volumes.values() | list)}] }}"
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Create service directories
become: true
ansible.builtin.file:
path: "{{ local_datastore_mount }}{{ item.1 }}"
state: directory
owner: "{{ item.0.user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0770
loop: "{{ _stack_volume_directories | subelements('volumes') }}"
- name: Deploy stack
vars:
ansible_python_interpreter: "{{ skylab_ansible_venv }}/bin/python"
community.docker.docker_stack:
name: "{{ item.key }}"
compose:
- "{{ skylab_compose_dir }}/{{ item.key }}.yaml"
prune: false
state: present
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Configure reverse proxy
run_once: true
block:
- name: Create nginx config
when: item.value.domain is defined
ansible.builtin.template:
src: stack-nginx.conf.j2
dest: "{{ local_datastore_mount }}/appdata/nginx/conf.d/{{ item.key }}.conf"
owner: "{{ ansible_user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0464
loop: "{{ _services | dict2items }}"
loop_control:
label: "{{ item.value.domain | default(item.key) }}"

View File

@@ -5,8 +5,9 @@ function _parse_git_branch() {
export PS1="\[\e[0;97m\]\[\e[37m\e[1m\]\u\[\e[1;94m\]@\[\e[94m\]\H\[\e[37m\]:\w\[\e[33m\]\[\e[0;33m\]\$(_parse_git_branch) \[\e[37m\]\[\e[0;97m\]$\[\e[0m\] " export PS1="\[\e[0;97m\]\[\e[37m\e[1m\]\u\[\e[1;94m\]@\[\e[94m\]\H\[\e[37m\]:\w\[\e[33m\]\[\e[0;33m\]\$(_parse_git_branch) \[\e[37m\]\[\e[0;97m\]$\[\e[0m\] "
export rc=/home/$USERNAME/.bashrc export rc=/home/$USERNAME/.bashrc
export VIRTUALENV_DIR=/home/$USERNAME/.venvs export VIRTUALENV_DIR=/home/$USERNAME/.venvs
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt
random() { function random() {
if [[ $# -eq 0 ]]; then if [[ $# -eq 0 ]]; then
num=32 num=32
else else
@@ -19,9 +20,10 @@ function up() { cd $(eval printf '../'%.0s {1..$1}); }
function pipin() { pip freeze | grep $1; } function pipin() { pip freeze | grep $1; }
function continuous () { while true; do ${@}; sleep 3; done; }
alias bk='cd -' alias bk='cd -'
alias fuck='sudo $(history -p \!\!)' alias fuck='sudo $(history -p \!\!)'
alias ls='ls -lshF --color --group-directories-first --time-style=long-iso'
alias version='uname -orp && lsb_release -a | grep Description' alias version='uname -orp && lsb_release -a | grep Description'
alias activate='source ./bin/activate' alias activate='source ./bin/activate'
alias cls='clear' alias cls='clear'
@@ -32,3 +34,4 @@ alias whatismyip='curl https://icanhazip.com/'
alias uuid="python3 -c 'import uuid; print(uuid.uuid4());'" alias uuid="python3 -c 'import uuid; print(uuid.uuid4());'"
alias epoch="python3 -c 'import time; print(time.time());'" alias epoch="python3 -c 'import time; print(time.time());'"
alias uptime="command uptime --pretty" alias uptime="command uptime --pretty"
alias unmount="umount"

View File

@@ -0,0 +1,137 @@
#!/usr/bin/env bash
set -o pipefail
declare FMT_RESET
declare FMT_BOLD
declare FMT_GREEN
declare FMT_RED
declare NL
FMT_RESET=$(printf "\\e[0m")
FMT_BOLD=$(printf "\\e[1m")
FMT_GREEN=$(printf "\\e[32m")
FMT_RED=$(printf "\\e[31m")
NL=$'\n'
readonly FMT_RESET
readonly FMT_BOLD
readonly FMT_GREEN
readonly FMT_RED
readonly NL
function usage() {
cat << __EOF__
${FMT_GREEN}$(basename "$0")${FMT_RESET}: \
Ping hosts and print status
${FMT_BOLD}Usage:${FMT_RESET}
$(basename "$0") [-h] [--service|--network]
${FMT_GREEN}-h --help${FMT_RESET}
Print this message and exit.
${FMT_GREEN}--services${FMT_RESET}
Report service status
${FMT_GREEN}--network${FMT_RESET}
Report network status
__EOF__
}
function _fmt_online() { echo "${FMT_BOLD}${FMT_GREEN}ONLINE${FMT_RESET}"; }
function _fmt_offline() { echo "${FMT_BOLD}${FMT_RED}OFFLINE${FMT_RESET}"; }
function _test_cmd() { if eval "$1" &>/dev/null ; then echo "${2}~$(_fmt_online)"; else echo "${2}~$(_fmt_offline)"; fi }
function _test_ping() { _test_cmd "ping -W 2 -c 1 ${1}" "${2}"; }
function _test_curl_head() { _test_cmd "curl --fail --head ${1}" "${2}"; }
function _test_curl_get() { _test_cmd "curl --fail --get ${1}" "${2}"; }
function _test_curl_insecure() { _test_cmd "curl --fail --head --insecure ${1}" "${2}"; }
function _test_netcat() { _test_cmd "nc -z ${1} ${2}" "${3}"; }
function network() {
local uplink_address="1.1.1.1"
declare -a infra=("core.en1.local" "switch.en1.local" "wap-1.en1.local" "wap-2.en1.local" "wap-3.en1.local" "printer.en1.local")
declare -a infra_names=("Core Router" "Core Switch" "Wireless AP 1" "Wireless AP 2" "Wireless AP 3" "Printer")
declare -a lab=("cluster.skylab.enp.one" "pegasus.skylab.enp.one" "saturn.skylab.enp.one" "orion.skylab.enp.one" "iridium.skylab.enp.one" "en2.enp.one")
declare -a lab_names=("Cluster" "Pegasus" "Saturn" "Orion" "Iridium" "Hubble")
local output=$(_test_ping "$uplink_address" "UPLINK")
output+="${NL}";
output+="${NL}INFRASTRUCTURE~STATE${NL}"
for (( index=0; index<"${#infra[@]}"; index++ )); do
output+=$(_test_ping "${infra[$index]}" "${infra_names[$index]}")
output+="${NL}"
done
output+="${NL}HOMELAB~STATE${NL}"
for (( index=0; index<"${#lab[@]}"; index++ )); do
output+=$(_test_ping "${lab[$index]}" "${lab_names[$index]}")
output+="${NL}"
done
column -e -t -s '~' <<<"$output"
}
function services() {
local output="INTERNAL~STATE${NL}"
output+=$(_test_netcat "cluster.skylab.enp.one" "53" "AdGuard DNS")
output+="${NL}"
output+=$(_test_netcat "core.en1.local" "53" "Fallback DNS")
output+="${NL}"
output+=$(_test_curl_insecure "https://cluster.skylab.enp.one:8443/status" "Ubiquiti WLC")
output+="${NL}"
output+="${NL}PUBLIC~STATE${NL}"
output+=$(_test_curl_head "https://pms.enp.one/web/index.html" "Plex Media Server")
output+="${NL}"
output+=$(_test_netcat "cluster.skylab.enp.one" "25565" "Minecraft Server")
output+="${NL}"
output+=$(_test_curl_get "https://vcs.enp.one/api/v1/version" "Version Control")
output+="${NL}"
output+=$(_test_curl_get "https://ssv.enp.one/api/alive" "Bitwarden")
output+="${NL}"
output+=$(_test_curl_head "https://cdn.enp.one/heartbeat" "Digital Ocean CDN")
output+="${NL}"
output+=$(_test_curl_head "https://doc.enp.one/" "Documentation")
output+="${NL}"
output+=$(_test_curl_head "https://enpaul.net/" "enpaul.net")
output+="${NL}"
output+=$(_test_curl_head "https://allaroundhere.org/" "allaroundhere.org")
output+="${NL}"
output+=$(_test_curl_head "https://enp.one/" "enp.one")
output+="${NL}"
column -e -t -s'~' <<<"$output"
}
function main() {
if [[ "$1" =~ ^(-h|--help)$ ]]; then
usage;
return 0
fi
if [[ "$1" = "--network" ]]; then
network;
return 0
fi
if [[ "$1" = "--services" ]]; then
services;
return 0
fi
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "${@}"
fi

View File

@@ -2,6 +2,9 @@
- name: Check cluster state - name: Check cluster state
hosts: cluster hosts: cluster
any_errors_fatal: true any_errors_fatal: true
pre_tasks:
- name: Configure remot execution environment
ansible.builtin.import_tasks: tasks/meta/bootstrap-remote-env.yaml
tasks: tasks:
- name: Validate user input - name: Validate user input
run_once: true run_once: true

View File

@@ -1,5 +1,5 @@
--- ---
- ansible.builtin.import_playbook: node-down.yaml - ansible.builtin.import_playbook: skylab.core.node_down
- name: Shutdown node - name: Shutdown node
hosts: "{{ node }}" hosts: "{{ node }}"

View File

@@ -5,9 +5,11 @@
- name: skylab_datastore_encryption_password - name: skylab_datastore_encryption_password
prompt: Enter datastore block decryption password prompt: Enter datastore block decryption password
private: true private: true
pre_tasks:
- name: Configure remote execution environment
ansible.builtin.import_tasks: tasks/meta/bootstrap-remote-env.yaml
roles: roles:
- role: datastore - role: skylab.core.datastore
when: "'datastore' in skylab_roles | default([])"
tasks: tasks:
- name: Fetch node swarm ID - name: Fetch node swarm ID
ansible.builtin.command: ansible.builtin.command:
@@ -25,12 +27,12 @@
- name: Determine node addresses - name: Determine node addresses
vars: vars:
_node_addresses: _node_addresses:
- "{{ lookup('vars', 'ansible_' + skylab_cluster.interface.access).ipv4.address | ansible.netcommon.ipaddr('host/prefix') }}" - "{{ (lookup('vars', 'ansible_' + skylab_cluster.interface.access).ipv4.address + '/' + lookup('vars', 'ansible_' + skylab_cluster.interface.access).ipv4.netmask) | ansible.netcommon.ipaddr('host/prefix') }}"
ansible.builtin.set_fact: ansible.builtin.set_fact:
_node_addresses: "{{ _node_addresses + [item.address | ansible.netcommon.ipaddr('host/prefix')] }}" _node_addresses: "{{ _node_addresses + [(item.address + '/' + item.netmask) | ansible.netcommon.ipaddr('host/prefix')] }}"
loop: "{{ lookup('vars', 'ansible_' + skylab_cluster.interface.access).ipv4_secondaries }}" loop: "{{ lookup('vars', 'ansible_' + skylab_cluster.interface.access).ipv4_secondaries }}"
loop_control: loop_control:
label: "{{ item.address }}" label: "{{ (item.address + '/' + item.netmask) | ansible.netcommon.ipaddr('host/prefix') }}"
- name: Determine cluster access addresses - name: Determine cluster access addresses
run_once: true run_once: true

View File

@@ -50,9 +50,7 @@
key: https://archive.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{{ ansible_distribution_major_version }} key: https://archive.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{{ ansible_distribution_major_version }}
- import_playbook: skylab.core.update
- import_playbook: update.yaml - import_playbook: skylab.core.configure
- import_playbook: configure.yaml

View File

@@ -1,10 +1,12 @@
--- ---
- name: Install CentOS 8 python bindings - name: Install CentOS 8 python bindings
when: ansible_distribution == "Rocky" when: ansible_distribution == "Rocky" or ansible_distribution == "Fedora"
become: true become: true
ansible.builtin.dnf: ansible.builtin.dnf:
state: present state: present
name: name:
- libffi-devel
- python3-devel
- python3-libselinux - python3-libselinux
- python3-policycoreutils - python3-policycoreutils
- python3-firewall - python3-firewall

View File

@@ -6,7 +6,7 @@
key: edgeos key: edgeos
- name: Group supported Linux hosts - name: Group supported Linux hosts
when: ansible_distribution == "Rocky" when: ansible_distribution == "Rocky" or ansible_distribution == "Fedora"
changed_when: false changed_when: false
group_by: group_by:
key: linux key: linux

View File

@@ -7,11 +7,11 @@ x-global-env: &globalenv
LOCAL_GID: "{{ _app_account.uid }}" LOCAL_GID: "{{ _app_account.uid }}"
ASPNETCORE_ENVIRONMENT: Production ASPNETCORE_ENVIRONMENT: Production
globalSettings__selfHosted: "true" globalSettings__selfHosted: "true"
globalSettings__baseServiceUri__vault: https://{{ app.domain }} globalSettings__baseServiceUri__vault: https://{{ app.publish.domain }}
globalSettings__baseServiceUri__api: https://{{ app.domain }}/api globalSettings__baseServiceUri__api: https://{{ app.publish.domain }}/api
globalSettings__baseServiceUri__identity: https://{{ app.domain }}/identity globalSettings__baseServiceUri__identity: https://{{ app.publish.domain }}/identity
globalSettings__baseServiceUri__admin: https://{{ app.domain }}/admin globalSettings__baseServiceUri__admin: https://{{ app.publish.domain }}/admin
globalSettings__baseServiceUri__notifications: https://{{ app.domain }}/notifications globalSettings__baseServiceUri__notifications: https://{{ app.publish.domain }}/notifications
globalSettings__baseServiceUri__internalNotifications: http://bitwarden_notifications:5000 globalSettings__baseServiceUri__internalNotifications: http://bitwarden_notifications:5000
globalSettings__baseServiceUri__internalAdmin: http://bitwarden_admin:5000 globalSettings__baseServiceUri__internalAdmin: http://bitwarden_admin:5000
globalSettings__baseServiceUri__internalIdentity: http://bitwarden_identity:5000 globalSettings__baseServiceUri__internalIdentity: http://bitwarden_identity:5000
@@ -22,7 +22,7 @@ x-global-env: &globalenv
globalSettings__sqlServer__connectionString: "Data Source=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=e934c0bb-3b5a-4e6b-b525-cd6d83004e1a;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True" globalSettings__sqlServer__connectionString: "Data Source=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=e934c0bb-3b5a-4e6b-b525-cd6d83004e1a;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True"
globalSettings__identityServer__certificatePassword: {{ app.settings.certificatePassword }} globalSettings__identityServer__certificatePassword: {{ app.settings.certificatePassword }}
globalSettings__attachment__baseDirectory: /etc/bitwarden/core/attachments globalSettings__attachment__baseDirectory: /etc/bitwarden/core/attachments
globalSettings__attachment__baseUrl: https://{{ app.domain }}/attachments globalSettings__attachment__baseUrl: https://{{ app.publish.domain }}/attachments
globalSettings__dataProtection__directory: /etc/bitwarden/core/aspnet-dataprotection globalSettings__dataProtection__directory: /etc/bitwarden/core/aspnet-dataprotection
globalSettings__logDirectory: /etc/bitwarden/logs globalSettings__logDirectory: /etc/bitwarden/logs
globalSettings__licenseDirectory: /etc/bitwarden/core/licenses globalSettings__licenseDirectory: /etc/bitwarden/core/licenses

View File

@@ -45,7 +45,7 @@ services:
USER_GID: "{{ _app_account.uid }}" USER_GID: "{{ _app_account.uid }}"
APP_NAME: ENP Version Control System APP_NAME: ENP Version Control System
RUN_MODE: prod RUN_MODE: prod
ROOT_URL: https://{{ app.domain }}/ ROOT_URL: https://{{ app.publish.domain }}/
DB_TYPE: sqlite3 DB_TYPE: sqlite3
DISABLE_REGISTRATION: "true" DISABLE_REGISTRATION: "true"
deploy: deploy:

View File

@@ -76,3 +76,24 @@ services:
restart_policy: restart_policy:
condition: any condition: any
delay: 24h delay: 24h
backup:
image: rockylinux:latest
hostname: backup
command: bash /datastore/backup/mkbkup.sh /datastore/
networks:
- meta
volumes:
- type: volume
source: meta-backup
target: /datastore/backup
read_only: false
- type: volume
source: meta-appdata
target: /datastore/appdata
read_only: true
deploy:
replicas: 1
restart_policy:
condition: any
delay: 24h

View File

@@ -0,0 +1,113 @@
---
version: '3.7'
volumes:
photoprism-database:
name: datastore/appdata/photoprism/database
driver: glusterfs
photoprism-metadata:
name: datastore/appdata/photoprism/metadata
photoprism-originals:
name: datastore/media/photoprism
driver: glusterfs
photoprism-import:
name: datastore/media/upload
driver: glusterfs
networks:
photoprism:
internal: true
name: photoprism
driver: overlay
ipam:
driver: default
config:
- subnet: 192.168.109.0/24
services:
app:
image: photoprism/photoprism:latest
hostname: app
depends_on:
- database
networks:
- photoprism
ports:
- published: 2342
target: 2342
protocol: tcp
mode: ingress
environment:
PHOTOPRISM_ADMIN_PASSWORD: "gm2auW34GNawZ8Dqiub8W8vOlvsHCnfj"
PHOTOPRISM_SITE_URL: "http://cluster.skylab.enp.one:2342/"
PHOTOPRISM_ORIGINALS_LIMIT: 5000
PHOTOPRISM_HTTP_COMPRESSION: "gzip"
PHOTOPRISM_DEBUG: "false"
PHOTOPRISM_PUBLIC: "false"
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_EXPERIMENTAL: "false"
PHOTOPRISM_DISABLE_CHOWN: "false"
PHOTOPRISM_DISABLE_WEBDAV: "false"
PHOTOPRISM_DISABLE_SETTINGS: "false"
PHOTOPRISM_DISABLE_TENSORFLOW: "false"
PHOTOPRISM_DISABLE_FACES: "false"
PHOTOPRISM_DISABLE_CLASSIFICATION: "false"
PHOTOPRISM_DARKTABLE_PRESETS: "false"
PHOTOPRISM_DETECT_NSFW: "false"
PHOTOPRISM_UPLOAD_NSFW: "true"
PHOTOPRISM_DATABASE_DRIVER: "mysql"
PHOTOPRISM_DATABASE_SERVER: "database:3306"
PHOTOPRISM_DATABASE_NAME: "photoprism"
PHOTOPRISM_DATABASE_USER: "photoprism"
PHOTOPRISM_DATABASE_PASSWORD: "KcIKhME9OwWKVz4tGyqI4VXzyDBs33Xp" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "Skylab Images"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
PHOTOPRISM_SITE_AUTHOR: "EN Paul"
HOME: "/photoprism"
PHOTOPRISM_UID: 1408
PHOTOPRISM_GID: 1408
## Hardware video transcoding config (optional)
# PHOTOPRISM_FFMPEG_BUFFERS: "64" # FFmpeg capture buffers (default: 32)
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_v4l2m2m" # Use Video4Linux for AVC transcoding (default: libx264)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_qsv" # Use Intel Quick Sync Video for AVC transcoding (default: libx264)
# PHOTOPRISM_INIT: "intel-graphics tensorflow-amd64-avx2" # Enable TensorFlow AVX2 & Intel Graphics support
## Enable TensorFlow AVX2 support for modern Intel CPUs (requires starting the container as root)
# PHOTOPRISM_INIT: "tensorflow-amd64-avx2"
user: "1408:1408"
working_dir: "/photoprism"
volumes:
- type: volume
source: photoprism-originals
target: /photoprism/originals
read_only: false
- type: volume
source: photoprism-metadata
target: /photoprism/storage
read_only: false
- type: volume
source: photoprism-import
target: /photoprism/import
read_only: true
deploy:
replicas: 1
database:
image: mariadb:10.6
hostname: database
command: mysqld --innodb-buffer-pool-size=128M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
networks:
- photoprism
volumes:
- type: volume
source: photoprism-database
target: /var/lib/mysql
read_only: false
environment:
MYSQL_ROOT_PASSWORD: insecure
MYSQL_DATABASE: photoprism
MYSQL_USER: photoprism
MYSQL_PASSWORD: KcIKhME9OwWKVz4tGyqI4VXzyDBs33Xp
deploy:
replicas: 1

View File

@@ -103,6 +103,6 @@ services:
- cache - cache
- proxy - proxy
environment: environment:
VIKUNJA_API_URL: https://{{ app.domain }}/api/v1 VIKUNJA_API_URL: https://{{ app.publish.domain }}/api/v1
deploy: deploy:
replicas: 1 replicas: 1

View File

@@ -0,0 +1,34 @@
# Ansible managed file - do not manually edit
#
server {
server_name {{ app.publish.domain }};
root /usr/share/nginx/html;
location / {
proxy_pass http://dockerloopback:{{ app.publish.http }}/;
proxy_set_header Host $host;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/{{ app.publish.domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ app.publish.domain }}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
listen 80;
listen [::]:80;
server_name {{ app.publish.domain }};
location ^~ /.well-known/acme-challenge/ {
proxy_pass http://dockerloopback:8088/.well-known/acme-challenge/;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
# EOF

View File

@@ -24,7 +24,7 @@
- vars/packages.yaml - vars/packages.yaml
tasks: tasks:
- name: Update system packages via DNF - name: Update system packages via DNF
when: ansible_distribution == "Rocky" when: ansible_distribution == "Rocky" or ansible_distribution == "Fedora"
become: true become: true
ansible.builtin.dnf: ansible.builtin.dnf:
name: "*" name: "*"
@@ -39,7 +39,7 @@
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
mode: 0644 mode: 0644
- name: Install universal packages - name: Install universal packages on Rocky
when: ansible_distribution == "Rocky" when: ansible_distribution == "Rocky"
become: true become: true
ansible.builtin.dnf: ansible.builtin.dnf:
@@ -47,6 +47,15 @@
state: present state: present
update_cache: true update_cache: true
- name: Install universal packages on Fedora
when: ansible_distribution == "Fedora"
become: true
ansible.builtin.dnf:
name: "{{ skylab_packages_global + skylab_packages_fedora }}"
state: present
update_cache: true
- name: Update unix accounts - name: Update unix accounts
hosts: linux hosts: linux
tags: tags:
@@ -75,38 +84,55 @@
cmd: 'grep "{{ skylab_group.name }}:" /etc/group | cut --delimiter : --fields 4 | tr "," "\n"' cmd: 'grep "{{ skylab_group.name }}:" /etc/group | cut --delimiter : --fields 4 | tr "," "\n"'
register: _existing_skylab_accounts register: _existing_skylab_accounts
- name: Determine deleted skylab users
vars:
_deleted_accounts: []
when: item not in (skylab_accounts | items2dict(key_name='name', value_name='uid'))
ansible.builtin.set_fact:
_deleted_accounts: "{{ _deleted_accounts + [item] }}"
loop: "{{ _existing_skylab_accounts.stdout_lines }}"
- name: Delete accounts
when: _deleted_accounts | default(false)
block:
- name: Delete removed user accounts - name: Delete removed user accounts
become: true become: true
when: item not in (skylab_accounts | items2dict(key_name='name', value_name='uid'))
ansible.builtin.user: ansible.builtin.user:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
loop: "{{ _existing_skylab_accounts.stdout_lines }}" loop: "{{ _deleted_accounts }}"
- name: Delete removed user groups - name: Delete removed user groups
become: true become: true
when: item not in (skylab_accounts | items2dict(key_name='name', value_name='uid'))
ansible.builtin.group: ansible.builtin.group:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
loop: "{{ _existing_skylab_accounts.stdout_lines }}" loop: "{{ _deleted_accounts }}"
- name: Delete removed user home directories - name: Delete removed user home directories
become: true become: true
when: item not in (skylab_accounts | items2dict(key_name='name', value_name='uid'))
ansible.builtin.file: ansible.builtin.file:
path: "/home/{{ item }}" path: "/home/{{ item }}"
state: absent state: absent
loop: "{{ _existing_skylab_accounts.stdout_lines }}" loop: "{{ _deleted_accounts }}"
- name: Determine active users
when: item.targets | default([]) | intersect(skylab_targets)
vars:
_active_accounts: []
ansible.builtin.set_fact:
_active_accounts: "{{ _active_accounts + [item] }}"
loop: "{{ skylab_accounts }}"
loop_control:
label: "{{ item.uid }},{{ item.name }}"
- name: Create account groups - name: Create account groups
when: item.targets | intersect(skylab_targets)
become: true become: true
ansible.builtin.group: ansible.builtin.group:
name: "{{ item.name }}" name: "{{ item.name }}"
gid: "{{ item.uid }}" gid: "{{ item.uid }}"
state: present state: present
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
@@ -114,17 +140,16 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
_determined_member_groups: "{{ _determined_member_groups | default({}) | combine({item.name: [ _determined_member_groups: "{{ _determined_member_groups | default({}) | combine({item.name: [
skylab_group.name, skylab_group.name,
'wheel' if (item.admin | default(false) and ansible_distribution == 'Rocky') else '', 'wheel' if (item.admin | default(false) and ansible_os_family == 'RedHat') else '',
'sudo' if (item.admin | default(false) and ansible_os_family == 'Debian') else '', 'sudo' if (item.admin | default(false) and ansible_os_family == 'Debian') else '',
skylab_group_admin.name if item.admin | default(false) else '', skylab_group_admin.name if item.admin | default(false) else '',
skylab_group_automation.name if item.service | default(false) else '', skylab_group_automation.name if item.service | default(false) else '',
]}) }}" ]}) }}"
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
- name: Create accounts - name: Create accounts
when: item.targets | intersect(skylab_targets)
become: true become: true
ansible.builtin.user: ansible.builtin.user:
name: "{{ item.name }}" name: "{{ item.name }}"
@@ -134,9 +159,13 @@
groups: "{{ _determined_member_groups[item.name] }}" groups: "{{ _determined_member_groups[item.name] }}"
comment: "{{ item.fullname | default('') }}" comment: "{{ item.fullname | default('') }}"
system: "{{ item.service | default(false) }}" system: "{{ item.service | default(false) }}"
generate_ssh_key: false generate_ssh_key: true
ssh_key_bits: 4096
ssh_key_passphrase: "{{ item.password }}"
ssh_key_comment: "{{ item.name }}@{{ inventory_hostname }}"
ssh_key_type: ed25519
password: "{{ item.password }}" password: "{{ item.password }}"
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
@@ -148,17 +177,10 @@
group: "{{ item.name }}" group: "{{ item.name }}"
owner: "{{ item.name }}" owner: "{{ item.name }}"
mode: 0700 mode: 0700
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
- name: Enforce root password
become: true
ansible.builtin.user:
name: root
password: "{{ skylab_root_password }}"
state: present
- name: Create SSH directory - name: Create SSH directory
become: true become: true
ansible.builtin.file: ansible.builtin.file:
@@ -167,31 +189,36 @@
group: "{{ item.name }}" group: "{{ item.name }}"
state: directory state: directory
mode: 0700 mode: 0700
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
- name: Update authorized keys - name: Update authorized keys
become: true become: true
when: item.targets | intersect(skylab_targets)
ansible.builtin.authorized_key: ansible.builtin.authorized_key:
user: "{{ item.name }}" user: "{{ item.name }}"
key: "{{ skylab_ssh_keys[item.name] | join('\n') }}" key: "{{ skylab_ssh_keys[item.name] | join('\n') }}"
state: present state: present
exclusive: true exclusive: true
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
- name: Enforce ownership of authorized keys - name: Enforce ownership of authorized keys
become: true become: true
when: item.targets | intersect(skylab_targets)
ansible.builtin.file: ansible.builtin.file:
path: /home/{{ item.name }}/.ssh/authorized_keys path: /home/{{ item.name }}/.ssh/authorized_keys
state: file state: file
owner: "{{ item.name }}" owner: "{{ item.name }}"
group: "{{ item.name }}" group: "{{ item.name }}"
mode: 0400 mode: 0400
loop: "{{ skylab_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:
label: "{{ item.uid }},{{ item.name }}" label: "{{ item.uid }},{{ item.name }}"
- name: Enforce root password
become: true
ansible.builtin.user:
name: root
password: "{{ skylab_root_password }}"
state: present

View File

@@ -3,13 +3,13 @@ skylab_accounts:
- name: enpaul - name: enpaul
uid: 1300 uid: 1300
fullname: Ethan N. Paul fullname: Ethan N. Paul
targets: [network, datastore, cluster, cloud] targets: [network, datastore, cluster, cloud, workstation]
admin: true admin: true
password: $6$H7jZEL2Ey93zfMTD$CzUlZkXDudPHgUMU/OFUn8/Yhzo8nBxoSI8thD15toIFlWN.iUfq/Jp5z3KpDCGTxyv.IbRTvE8dOVWjoRfgJ. password: $6$H7jZEL2Ey93zfMTD$CzUlZkXDudPHgUMU/OFUn8/Yhzo8nBxoSI8thD15toIFlWN.iUfq/Jp5z3KpDCGTxyv.IbRTvE8dOVWjoRfgJ.
- name: ansible - name: ansible
uid: 1400 uid: 1400
targets: [network, datastore, cluster, cloud] targets: [network, datastore, cluster, cloud, workstation]
admin: true admin: true
service: true service: true
password: $6$qNKmYg4y9YS4f5Gr$m0mAqEVbymPguj.1cS.pfclt33Okfmn1KhFC0r1iQ3eVvz/OIZY3x0qGmPnJ1zOXDWyKKs5hnlGTAeZgCh49C. password: $6$qNKmYg4y9YS4f5Gr$m0mAqEVbymPguj.1cS.pfclt33Okfmn1KhFC0r1iQ3eVvz/OIZY3x0qGmPnJ1zOXDWyKKs5hnlGTAeZgCh49C.

View File

@@ -27,3 +27,9 @@ skylab_packages_rocky:
- python3-virtualenv - python3-virtualenv
- systemd-networkd - systemd-networkd
- wget - wget
skylab_packages_fedora:
- bind-utils
- nc
- nfs-utils
- wget

View File

@@ -1,6 +1,6 @@
--- ---
skylab_services: skylab_services:
_meta: meta:
networks: networks:
ext: 192.168.99.0/24 ext: 192.168.99.0/24
volumes: volumes:
@@ -17,8 +17,7 @@ skylab_services:
loopback_address: 192.168.255.255 loopback_address: 192.168.255.255
minecraft: minecraft:
user: auto_minecraft user: autocraft
domain: mcs.enp.one
networks: networks:
ext: 192.168.102.0/24 ext: 192.168.102.0/24
volumes: volumes:
@@ -27,6 +26,8 @@ skylab_services:
25565: 25565 25565: 25565
versions: versions:
server: 1.16.5 server: 1.16.5
publish:
domain: mcs.enp.one
settings: settings:
admins: admins:
- ScifiGeek42 - ScifiGeek42
@@ -40,7 +41,6 @@ skylab_services:
gitea: gitea:
user: autotea user: autotea
domain: vcs.enp.one
networks: networks:
ext: 192.168.103.0/24 ext: 192.168.103.0/24
volumes: volumes:
@@ -48,12 +48,14 @@ skylab_services:
ports: ports:
3000: 3000 3000: 3000
22: 2222 22: 2222
publish:
domain: vcs.enp.one
http: 3000
versions: versions:
server: 1.15.4 server: 1.15.4
bitwarden: bitwarden:
user: autowarden user: autowarden
domain: ssv.enp.one
networks: networks:
internal: 192.168.104.0/24 internal: 192.168.104.0/24
external: 192.168.105.0/24 external: 192.168.105.0/24
@@ -87,6 +89,9 @@ skylab_services:
icons: 1.40.0 icons: 1.40.0
events: 1.40.0 events: 1.40.0
nginx: 1.40.0 nginx: 1.40.0
publish:
domain: ssv.enp.one
http: 8090
settings: settings:
certificatePassword: !vault | certificatePassword: !vault |
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
@@ -138,7 +143,6 @@ skylab_services:
adguard: adguard:
user: autoguard user: autoguard
domain: adguard.en1.local
networks: networks:
ext: 192.168.108.0/24 ext: 192.168.108.0/24
volumes: volumes:
@@ -149,6 +153,9 @@ skylab_services:
8064: 8084 8064: 8084
versions: versions:
server: v0.106.3 server: v0.106.3
publish:
domain: adguard.en1.local
http: 8064
settings: settings:
upstream: upstream:
- 1.1.1.1 - 1.1.1.1
@@ -156,7 +163,6 @@ skylab_services:
plex: plex:
user: autoplex user: autoplex
domain: pms.enp.one
networks: networks:
ext: 192.168.101.0/24 ext: 192.168.101.0/24
volumes: volumes:
@@ -172,6 +178,9 @@ skylab_services:
32414: 32414 32414: 32414
versions: versions:
server: latest server: latest
publish:
domain: pms.enp.one
http: 32400
settings: settings:
mediastore: mediastore.skylab.enp.one mediastore: mediastore.skylab.enp.one
internal_subnets: internal_subnets:
@@ -183,7 +192,6 @@ skylab_services:
unifi: unifi:
user: autounifi user: autounifi
domain: unifi.en1.local
networks: networks:
ext: 192.168.100.0/24 ext: 192.168.100.0/24
volumes: volumes:
@@ -198,10 +206,12 @@ skylab_services:
10001: 10001 10001: 10001
versions: versions:
wlc: "6.2" wlc: "6.2"
publish:
domain: unifi.en1.local
http: 8080
vikunja: vikunja:
user: autollama user: autollama
domain: org.enp.one
networks: networks:
ext: 192.168.107.0/24 ext: 192.168.107.0/24
volumes: volumes:
@@ -216,6 +226,9 @@ skylab_services:
proxy: latest proxy: latest
api: 0.18.1 api: 0.18.1
web: 0.18.1 web: 0.18.1
publish:
domain: org.enp.one
http: 8087
settings: settings:
database_password: !vault | database_password: !vault |
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256

View File

@@ -2,8 +2,8 @@
skylab_ssh_keys: skylab_ssh_keys:
enpaul: enpaul:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDi9rWRC15og/+3Jc3AMHOrlIc2BHaAX9PLbklz3qfFtSOp9bIScMcH5ZR6lyVSgP8RCEjI5HuZejDUJTXUQYfvEJeno//vmxn9Vw66lpMz/FSJ3JcDbjDVI1pe3A8mTOAS+AoVOEzCUOJVZJvdI272Hgf+QRBu+ONQ12u+2XYdVfLFDe7mAG+vEJRBatwb8B7Al+/LUpIrCuPm9PzMBtCMFjWGaqQgnyJYRSPIGxz9231XIjwhHLOQG1R0jLGuS37X+J49Y5JYDaHf9q9KH76GjdO2rOq6aGvwN93Y4Z+D2hMOklhD0Ez/ZE+I3ZUPV0e5pF28gsA6L7gTeqmSGpQaKdwjCUoU12VM70OVxng5p2+7DIc0k2np7rnvd4zybgn9OMM+TIO5M3c6ocDuNsEmRgfS3V99X5oh9qNy35UdBXV08j0wFoUo1KcyGwyNBYzKzvkkvtgJezVKmqSPKeBjMgMX4UsJsMn27Zosk0ZgoUwLFPO9Pg7uShncwgsTnvYDR1ws53PV832gc7A85ud/dC9Fjn6jBsMQaCFbiZktc5J8mv3cugQHQesbq8Y2aNVRu+ECb+KUvAEdPacWdBOkk0IvZ4PvLrAs2xehF6FYVqKVtPlJMaUAAwj9vVx7Nl2HnsSRIrCgxsMOTOhbbp/3NrvM8r6K7zKBzXg2TNgQeQ== enpaul@ph-1 - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDi9rWRC15og/+3Jc3AMHOrlIc2BHaAX9PLbklz3qfFtSOp9bIScMcH5ZR6lyVSgP8RCEjI5HuZejDUJTXUQYfvEJeno//vmxn9Vw66lpMz/FSJ3JcDbjDVI1pe3A8mTOAS+AoVOEzCUOJVZJvdI272Hgf+QRBu+ONQ12u+2XYdVfLFDe7mAG+vEJRBatwb8B7Al+/LUpIrCuPm9PzMBtCMFjWGaqQgnyJYRSPIGxz9231XIjwhHLOQG1R0jLGuS37X+J49Y5JYDaHf9q9KH76GjdO2rOq6aGvwN93Y4Z+D2hMOklhD0Ez/ZE+I3ZUPV0e5pF28gsA6L7gTeqmSGpQaKdwjCUoU12VM70OVxng5p2+7DIc0k2np7rnvd4zybgn9OMM+TIO5M3c6ocDuNsEmRgfS3V99X5oh9qNy35UdBXV08j0wFoUo1KcyGwyNBYzKzvkkvtgJezVKmqSPKeBjMgMX4UsJsMn27Zosk0ZgoUwLFPO9Pg7uShncwgsTnvYDR1ws53PV832gc7A85ud/dC9Fjn6jBsMQaCFbiZktc5J8mv3cugQHQesbq8Y2aNVRu+ECb+KUvAEdPacWdBOkk0IvZ4PvLrAs2xehF6FYVqKVtPlJMaUAAwj9vVx7Nl2HnsSRIrCgxsMOTOhbbp/3NrvM8r6K7zKBzXg2TNgQeQ== enpaul@ph-1
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8K74AXz6LBYfoXRbY1pKP+1rvi5BpjFOkg1uYuMM+q78toagSREpLrbjvPtoL8fkEFox4T9TUaME08ZP8560R6iRk35extTTiXquflEwvpsF+e9Lv8E712s/1ydJpkYoux1OohE4W5D9DjVMEW1tjXeb+9aDUcVml6YKMpKLpjEIVanyjHMN13XgswKZGoK3mVMnWxE36fbGVVfiFCvMr/BpjqGShRCxmvldzgq76i1BpTKi6omOjvpgRQcUJcDhYcHAUVSlNccgGLmlAPiUillA//pk84yczzH1dQBB6571Ab5ldoUDBU/hJ0W27aeOfrepup4hNuUt2oux+zAn+uetAuAWKU2Kd0Oo6L5IKObbAQLI0CXfyrmHlrYXwTyNMFleeOdw7s9lf2ra3YCYVXfMALdE6pp+HJLBxzg9kMBbTp6zkV7ZKi75AQhyBJA0s4+vRUccBtJit3Tls+aw/3rd9Dt9lLaXkE80khoKsUI0eiuXtPDlurGxkpcTe6Al/lChNA19pdKEUsBmhD6UUvMTYWlApmta/+xf0wDsSyHqJcnIGx8Qdtg3c4j1Ch+WXwbdOwk8XJrL0atWmv2ium1ll/arO2NFBmbwG1LG/lzJ1k/DoAiHrKrb1HdlwDk0O/7xF/zyC2mfVZKO36+g4XlA7wDJc0tB5vIymlEy2rw== enpaul@serico-nox - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8K74AXz6LBYfoXRbY1pKP+1rvi5BpjFOkg1uYuMM+q78toagSREpLrbjvPtoL8fkEFox4T9TUaME08ZP8560R6iRk35extTTiXquflEwvpsF+e9Lv8E712s/1ydJpkYoux1OohE4W5D9DjVMEW1tjXeb+9aDUcVml6YKMpKLpjEIVanyjHMN13XgswKZGoK3mVMnWxE36fbGVVfiFCvMr/BpjqGShRCxmvldzgq76i1BpTKi6omOjvpgRQcUJcDhYcHAUVSlNccgGLmlAPiUillA//pk84yczzH1dQBB6571Ab5ldoUDBU/hJ0W27aeOfrepup4hNuUt2oux+zAn+uetAuAWKU2Kd0Oo6L5IKObbAQLI0CXfyrmHlrYXwTyNMFleeOdw7s9lf2ra3YCYVXfMALdE6pp+HJLBxzg9kMBbTp6zkV7ZKi75AQhyBJA0s4+vRUccBtJit3Tls+aw/3rd9Dt9lLaXkE80khoKsUI0eiuXtPDlurGxkpcTe6Al/lChNA19pdKEUsBmhD6UUvMTYWlApmta/+xf0wDsSyHqJcnIGx8Qdtg3c4j1Ch+WXwbdOwk8XJrL0atWmv2ium1ll/arO2NFBmbwG1LG/lzJ1k/DoAiHrKrb1HdlwDk0O/7xF/zyC2mfVZKO36+g4XlA7wDJc0tB5vIymlEy2rw== enpaul@discovery
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHUXG01NQ7IahqBwLx+lqvbnhU5Cynt+Y4xCk2u5pwjU2KwKyRfqc5LUROU4mcFLuA1mP9uoMaYmiJ/rIWvM/A9OVplilCoSKXxWJW09fR/rOPmCn7pOR+CpFXBNOiRR0WoiDeu1D0tifbSuK/qOxKy6Lp9MH20Ma46d89xA57L9LX+B5CrwF9fR2FXIQGojCiFFyByaUgmzuDMi5mCafm3XlqaR1/wcqoA1YwqFFiGR3gVylSbOmB/Q4GnnyLpBbcYAc5AQnbnD4LlM5biEsLNy7vtQj9s0SeloUkzsJ112dNozdwTI/tOWbINVM+o3AH4B2baTQayWK/UrG9sivjHgEz5Jk5A4xAbUWC1MrH7WHo7vevHu4AT+DiPLkmHli9Ztu0DqJuenheJDyRLfWwDPvIpoY9/AsbVZ/UXqRVbfIB4jV00IHneEg4zj0AdWbSHDz55BZ23JItpuU4i37cO9Cbo2tQYqZjgM5VAlZXwhNPUF7pxWJJxGFqiB5MTQM0LZcrmXpToxBPa0BSDmIcjvLP6NQWk1u+Fdjunyx/q9Gmlc3vFtFEz7swWCuKp4DavyUXFeWwSKt4dDRZyPPdSYrKxDPCncSaKeCv+G5sx4RyQLJjpx14tisnnZP0O5b5S6j3PfGzjgnNBhzl/xIzM5moUqPF7R2laOKh9CBdoQ== enpaul@vigil-nox - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ3ron1rnTp4t9iyB2VGY5jNuOuJcOgZD3KewjPqOijA enpaul@voyager
ansible: ansible:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDN/E/zjwCruZf+mboBeBAtNFBInWMvdm6TjwpIg6jVoGgRmYQxEfIcqDSfBTQQ0gbyE3udTdTUDRLRu7ADktzL9J0IepEaYARfz8SANS/Hx2MR0NNy8DArrSFJCOillDA7E7UmNPIPeQl0O76p2ZjEDy6qZnTiW8eOtD7LCzJp4eGJanUPFhag8f4aSNbmiHGR25Zuk82w2/+KrqiI3gO0+jNlnPBf+XHNnFbtUIroupRfxgLdk1OahmkWHTSHkDtXiYrWIISarrHCgVqHTHo1KIX5+MPOH4S5VLB1kaY/O7+g/XlFrAciw8m0zjyBq0ILb+YTSrL9PYnSBtnHAVGJv2bB+TgCfF/nhQGqoqBqqQHFnX0y3JygmDTJMO+aE5wlvI5Laki7EHYPU4fL+Ge76l/dG9j2anw4/iHklbfk1UOxnLvJl593GAlILg1Kd8xx9VfYzVZ7GZym2zq3NI4uQ77T1H4iGoE67zarkn3peKacjX/KARq4weVvs3irHIHibnIuh/TGcS4eiQoNdPxsSA2wRKB6jeuXiV65F1rUDNGs80wcJmsAbZN8/u9Tt0o/Xc+L/LVhV0yrSeBUxzXtlaS+RfcteBXByO3xfC112Cj5grKVki5xWN9AY42Y6JhT3OyiO33dKUMEF/KfiEWWAfvQr/t1CI/rdcEbv3pyUw== enpaul@serico-nox-ansible - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP5TGKururOa1Y+cbv8AWXYI5zhfZCDV0fsBG+33IYUc enpaul@ansible.voyager
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDIbXaUzVqDDKDSC1iO/nOmxIcJoOoMvXE+CJRobEdpkkYSBmlPfburJvGMDMQ3O/88OfgBrG5S7HKlbgVPGEII0Vpsk5iwzOk5Tmo03nLz02Ilx1xXYxTrjUSwnexzbHpluHmqunKEIUVTMHpDz2m4UPgZ4ECsGp9/6n6+n//uLeJ4fQUO9x4L+VMbpDrtfpKN7/P6U30XBIb9bZuKznVPtqTmCy/BFkxTkIn9QKqDh5d49FY/xkOjy1K9zTWb78DFzBRf4sGEykrp19N6inL0eRstGSZAKhqL+qdRXOy/7n6l0u+CdXWl9ZFVXRFhVdAhYOgkEvtuqoasK1Fk3OMqP6SflFanuDiFBostfgfrf8SUV+7CFvOuSpEWgTqx/jPFZV4Vr6wx5ZFVs02OzZ6TJFaEHaLvOE/R3iLOiuFcvqVNpvstLiyiigsj1+DwhDJcwOr3DaEsNdUbv0BTI2P03wtHJtBQw5CaVr5zCBDEeUsL0bBVQdq+6d0NT+CPJNxSZlTmmrBBbgkpupxdnmX6VVBYfXnylsE8UZxY1d7yxba3+Wzp2yvlr2MVocwQmMTPEqimIsW0hsQ8iXi1nrDXecSojlDAeu+LBFuaCxO8H59GrrVWVTI2dAPLEcP+stNGLHqKZuh62t5TnmxuMMi0SY6jH7KiKmusD4fYafzrlQ== enpaul@vigil-nox-ansible - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDN/E/zjwCruZf+mboBeBAtNFBInWMvdm6TjwpIg6jVoGgRmYQxEfIcqDSfBTQQ0gbyE3udTdTUDRLRu7ADktzL9J0IepEaYARfz8SANS/Hx2MR0NNy8DArrSFJCOillDA7E7UmNPIPeQl0O76p2ZjEDy6qZnTiW8eOtD7LCzJp4eGJanUPFhag8f4aSNbmiHGR25Zuk82w2/+KrqiI3gO0+jNlnPBf+XHNnFbtUIroupRfxgLdk1OahmkWHTSHkDtXiYrWIISarrHCgVqHTHo1KIX5+MPOH4S5VLB1kaY/O7+g/XlFrAciw8m0zjyBq0ILb+YTSrL9PYnSBtnHAVGJv2bB+TgCfF/nhQGqoqBqqQHFnX0y3JygmDTJMO+aE5wlvI5Laki7EHYPU4fL+Ge76l/dG9j2anw4/iHklbfk1UOxnLvJl593GAlILg1Kd8xx9VfYzVZ7GZym2zq3NI4uQ77T1H4iGoE67zarkn3peKacjX/KARq4weVvs3irHIHibnIuh/TGcS4eiQoNdPxsSA2wRKB6jeuXiV65F1rUDNGs80wcJmsAbZN8/u9Tt0o/Xc+L/LVhV0yrSeBUxzXtlaS+RfcteBXByO3xfC112Cj5grKVki5xWN9AY42Y6JhT3OyiO33dKUMEF/KfiEWWAfvQr/t1CI/rdcEbv3pyUw== enpaul@ansible.discovery

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
[grafana]
name=grafana
baseurl=https://packages.grafana.com/enterprise/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt

View File

@@ -0,0 +1,22 @@
# Ansible managed file - DO NOT EDIT
#
# https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04
#
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/nginx/ssl-dhparam.pem;
# EOF

View File

@@ -0,0 +1,12 @@
---
- name: restart-nginx
become: true
ansible.builtin.systemd:
name: nginx
state: restarted
- name: restart-grafana
become: true
ansible.builtin.systemd:
name: grafana-server
state: restarted

View File

@@ -0,0 +1,48 @@
---
- name: Install Grafana Enterprise repository
become: true
ansible.builtin.copy:
src: grafana.repo
dest: /etc/yum.repos.d/grafana.repo
owner: root
group: "{{ ansible_user }}"
mode: 0644
register: _grafana_repo
- name: Install Grafana repository GPG key
become: true
ansible.builtin.rpm_key:
state: present
key: https://packages.grafana.com/gpg.key
- name: Install Grafana
become: true
ansible.builtin.dnf:
name: grafana
state: present
update_cache: "{{ _grafana_repo.changed }}"
- name: Enable and start Grafana
become: true
ansible.builtin.systemd:
name: grafana-server
state: started
enabled: true
- name: Fetch installed grafana plugins
become: true
ansible.builtin.command:
cmd: grafana-cli plugins ls
changed_when: false
register: _grafana_plugins_raw
- name: Install plugins
become: true
ansible.builtin.command:
cmd: grafana-cli plugins install {{ item }}
changed_when: item not in _grafana_plugins_raw.stdout
notify: [restart-grafana]
loop:
- marcusolsson-json-datasource
- grafana-clock-panel
- ayoungprogrammer-finance-datasource

View File

@@ -0,0 +1,6 @@
---
- name: Install and configure Grafana
ansible.builtin.import_tasks: grafana.yaml
- name: Install and configure Nginx
ansible.builtin.import_tasks: nginx.yaml

View File

@@ -0,0 +1,107 @@
---
- name: Install nginx
become: true
ansible.builtin.dnf:
name: nginx
state: present
- name: Enable and start nginx
become: true
ansible.builtin.systemd:
name: nginx
state: started
enabled: true
- name: Configure firewall for Nginx
become: true
ansible.posix.firewalld:
service: "{{ item }}"
state: enabled
zone: internal
permanent: true
immediate: true
loop:
- http
- https
- name: Configure SELinux for Nginx
when: ansible_selinux.status | default("") == "enabled"
become: true
ansible.posix.seboolean:
name: httpd_can_network_connect
state: true
persistent: true
notify: [restart-nginx]
- name: Create certificate directory
become: true
ansible.builtin.file:
path: "{{ dashboard_certificate_directory }}"
state: directory
owner: nginx
group: "{{ ansible_user }}"
mode: 0570
- name: Generate X509 private key
become: true
vars:
ansible_python_interpreter: "{{ skylab_ansible_venv }}/bin/python"
community.crypto.openssl_privatekey:
path: "{{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.key"
type: RSA
size: 8192
passphrase: "{{ dashboard_certificate_password }}"
cipher: auto
owner: nginx
group: "{{ ansible_user }}"
mode: 0460
- name: Install private key password file
become: true
ansible.builtin.copy:
content: "{{ dashboard_certificate_password }}"
dest: "{{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.password"
owner: nginx
group: "{{ ansible_user }}"
mode: 0460
- name: Create self-signed certificate
become: true
vars:
ansible_python_interpreter: "{{ skylab_ansible_venv }}/bin/python"
community.crypto.x509_certificate:
path: "{{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.pem"
privatekey_path: "{{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.key"
privatekey_passphrase: "{{ dashboard_certificate_password }}"
provider: selfsigned
owner: nginx
group: "{{ ansible_user }}"
mode: 0460
notify: [restart-nginx]
- name: Copy nginx SSL parameters
become: true
ansible.builtin.copy:
src: ssl-options.conf
dest: /etc/nginx/ssl-options.conf
owner: nginx
group: "{{ ansible_user }}"
mode: 0664
notify: [restart-nginx]
- name: Export Diffie-Hellman parameters
become: true
ansible.builtin.command:
cmd: openssl dhparam -out /etc/nginx/ssl-dhparam.pem 2048
creates: /etc/nginx/ssl-dhparam.pem
notify: [restart-nginx]
- name: Configure nginx server
become: true
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/{{ dashboard_hostname }}.conf
owner: nginx
group: "{{ ansible_user }}"
mode: 0444
notify: [restart-nginx]

View File

@@ -0,0 +1,29 @@
# Ansible managed file - DO NOT MANUALLY EDIT
#
server {
server_name {{ dashboard_hostname }};
root /usr/share/nginx/html;
location / {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
}
listen 443 ssl http2;
ssl_certificate {{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.pem;
ssl_certificate_key {{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.key;
ssl_password_file {{ dashboard_certificate_directory }}/{{ dashboard_hostname }}.password;
include /etc/nginx/ssl-options.conf;
}
server {
if ($host = {{ dashboard_hostname }}) {
return 301 https://$host$request_uri;
}
server_name {{ dashboard_hostname }};
listen 80;
return 404;
}
#
# EOF

View File

@@ -0,0 +1,15 @@
---
dashboard_certificate_directory: /etc/nginx/certs
dashboard_certificate_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62373265623036656632396637363539313437656433656461356561393538333536303961363462
3964353831633165363430313533623563343732623930630a393030393336613563313431306233
62393235303234336365313138633137663430653061343737616466303136616130643061356566
3165313038393163340a396365643335343332333335363539326635633466313264373639353930
36646462396139346432353233646635303031613639323266366235373132346363653431323666
38336365303431646530613030613437663035613332653865366432636238303437323633666239
64366435353762656362666531393865383639343461616365316634326334623733653664666161
63366234646466326531363666633966326462373562313839393731633931383762306663396562
65663031653661333439373461333234613863623364643464323863656630386561316565353232
35313338373631356231376361346662353365373030653965626434336339613936656138656637
666430306334623563306236616663623438

View File

@@ -0,0 +1,11 @@
/####### /## /## /## /## /## /####### /#####
/## /##___/## /##___/## /## /##___/## /##__/##
/##____ /####### /######## /## /######## /######
######## /## |## /## /## /## /## /##__/##
/## /## |## /####### /## /## /## /######
____/## /##_____
/###### ******************* /######## ************
✨ {{ skylab_description }} @{{ skylab_location }}
{{ ' ' }}

View File

@@ -39,7 +39,7 @@
- name: Add administrators to docker group - name: Add administrators to docker group
become: true become: true
when: item.admin | default(false) and 'cluster' in item.targets when: item.admin | default(false) and 'cluster' in (item.targets | default([]))
ansible.builtin.user: ansible.builtin.user:
name: "{{ item.name }}" name: "{{ item.name }}"
group: "{{ item.name }}" group: "{{ item.name }}"

View File

@@ -31,7 +31,6 @@
- name: Determine gluster servers - name: Determine gluster servers
run_once: true run_once: true
when: "'datastore' in hostvars[item].skylab_roles | default([])"
vars: vars:
_docker_glusterfs_hostnames: [] _docker_glusterfs_hostnames: []
ansible.builtin.set_fact: ansible.builtin.set_fact:

View File

@@ -29,6 +29,7 @@
listen_addr: "{{ lookup('vars', 'ansible_' + skylab_cluster.interface.internal).ipv4.address }}" listen_addr: "{{ lookup('vars', 'ansible_' + skylab_cluster.interface.internal).ipv4.address }}"
remote_addrs: "{{ _docker_swarm_manager_addresses }}" remote_addrs: "{{ _docker_swarm_manager_addresses }}"
join_token: "{{ _docker_swarm_join_token.stdout.strip() }}" join_token: "{{ _docker_swarm_join_token.stdout.strip() }}"
timeout: 1200
- name: Fetch node swarm ID - name: Fetch node swarm ID
ansible.builtin.command: ansible.builtin.command:

View File

@@ -0,0 +1,2 @@
[org/gnome/login-screen]
disable-user-list=true

View File

@@ -0,0 +1,2 @@
[org/gnome/mutter]
experimental-features=['scale-monitor-framebuffer']

View File

@@ -0,0 +1,47 @@
if [ -f `which powerline-daemon` ]; then
powerline-daemon -q
POWERLINE_BASH_CONTINUATION=1
POWERLINE_BASH_SELECT=1
. /usr/share/powerline/bash/powerline.sh
fi
export NVM_DIR="$HOME/.nvm"
export PROJECTS_DIR="$HOME/projects"
function gg() {
cd "$PROJECTS_DIR/$1";
if [ -f "$PROJECTS_DIR/$1/ansible.cfg" ]; then
ANSIBLE_CONFIG="$PROJECTS_DIR/$1/ansible.cfg" ANSIBLE_COLLECTIONS_PATH="$PROJECTS_DIR/$1/.ansible" poetry shell;
elif [ -f "$PROJECTS_DIR/$1/pyproject.toml" ]; then
poetry shell;
fi
}
mpw() {
_copy() {
if hash pbcopy 2>/dev/null; then
pbcopy
elif hash xclip 2>/dev/null; then
xclip -selection clip
else
cat; echo 2>/dev/null
return
fi
echo >&2 "Copied!"
}
# Empty the clipboard
:| _copy 2>/dev/null
# Ask for the user's name and password if not yet known.
MPW_FULLNAME="Ethan Paul"
# Start Master Password and copy the output.
printf %s "$(MPW_FULLNAME=$MPW_FULLNAME command mpw "$@")" | _copy
}
alias explorer='nautilus'
alias doc='cd ~/Documents'
alias dn='cd ~/Downloads'
alias prun="poetry run"
alias psync="poetry install --remove-untracked"

View File

@@ -0,0 +1,3 @@
user-db:user
system-db:gdm
file-db:/usr/share/gdm/greeter-dconf-defaults

View File

@@ -0,0 +1,2 @@
user-db:user
system-db:local

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

View File

@@ -0,0 +1,6 @@
---
- name: dconf-update
become: true
changed_when: true
ansible.builtin.command:
cmd: dconf update

View File

@@ -0,0 +1,144 @@
---
- name: Install user bashrc
become: true
ansible.builtin.copy:
src: bashrc.sh
dest: ~{{ item }}/.bashrc_ansible
owner: "{{ ansible_user }}"
group: "{{ item }}"
mode: 0644
loop: "{{ _local_human_users }}"
- name: Configure user bashrc loading
become: true
ansible.builtin.lineinfile:
path: ~{{ item }}/.bashrc
line: source ~/.bashrc_ansible
state: present
loop: "{{ _local_human_users }}"
- name: Configure local bash completions loading
become: true
ansible.builtin.lineinfile:
path: ~{{ item }}/.bashrc
line: source ~/.config/bash_completions
state: present
loop: "{{ _local_human_users }}"
- name: Configure bash completions
become: true
ansible.builtin.blockinfile:
path: ~{{ item }}/.config/bash_completions
create: true
block: >-
function _gg_completion() {
local cur=${COMP_WORDS[COMP_CWORD]};
COMPREPLY=( $(compgen -W "$(command ls $PROJECTS_DIR)" -- $cur) );
}
complete -F _gg_completion gg
owner: "{{ ansible_user }}"
group: "{{ item }}"
mode: 0664
loop: "{{ _local_human_users }}"
- name: Enforce ownership of the SSH keys
become: true
ansible.builtin.file:
path: ~{{ item.0 }}/.ssh/id_ed25519{{ item.1 }}
state: file
owner: "{{ item.0 }}"
group: "{{ item.0 }}"
loop: "{{ _local_human_users | product(['', '.pub']) }}"
- name: Configure dconf setting
become: true
block:
- name: Create dconf config directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: "{{ ansible_user }}"
mode: 0755
loop:
- /etc/dconf/profile
- /etc/dconf/db/gdm.d
- name: Create global dconf config
ansible.builtin.copy:
src: gdm-system
dest: /etc/dconf/profile/gdm
owner: root
group: "{{ ansible_user }}"
mode: 0644
notify:
- dconf-update
- name: Create user dconf config
ansible.builtin.copy:
src: gdm-user
dest: /etc/dconf/profile/user
owner: root
group: "{{ ansible_user }}"
mode: 0644
notify:
- dconf-update
- name: Disable user list
ansible.builtin.copy:
src: 00-disable-user-list
dest: /etc/dconf/db/gdm.d/00-disable-user-list
owner: root
group: "{{ ansible_user }}"
mode: 0644
notify:
- dconf-update
- name: Enable fractional scaling
ansible.builtin.copy:
src: 00-enable-fractional-scaling
dest: /etc/dconf/db/local.d/00-enable-fractional-scaling
owner: root
group: "{{ ansible_user }}"
mode: 0644
notify:
- dconf-update
- name: Install themes
become: true
block:
- name: Create local themes directory
ansible.builtin.file:
path: ~{{ item }}/.themes
state: directory
owner: "{{ item }}"
group: "{{ item }}"
mode: 0750
loop: "{{ _local_human_users }}"
- name: Unarchive LightningBug into local directory
ansible.builtin.unarchive:
src: lightningbug-dark.tar.gz
dest: ~{{ item }}/.themes
owner: "{{ item }}"
group: "{{ item }}"
loop: "{{ _local_human_users }}"
- name: Install wallpaper
become: true
ansible.builtin.copy:
src: wallpaper-{{ inventory_hostname }}.jpg
dest: ~{{ item }}/Pictures/wallpaper.jpg
owner: "{{ item }}"
group: "{{ item }}"
loop: "{{ _local_human_users }}"
- name: Link external media directory
become: true
ansible.builtin.file:
path: ~{{ item }}/Drives
src: /run/media/{{ item }}
state: link
force: true
loop: "{{ _local_human_users }}"

View File

@@ -0,0 +1,59 @@
---
- name: Check for MPW binary
ansible.builtin.stat:
path: /usr/local/bin/mpw
register: _mpw_binary_stat
- name: Install MPW
when: (not _mpw_binary_stat.stat.exists) or (force_reinstall | default(false))
block:
- name: Install build dependencies on Fedora
when: ansible_distribution == "Fedora"
become: true
ansible.builtin.dnf:
name:
- libsodium-devel
state: present
- name: Create temporary build directory
ansible.builtin.tempfile:
prefix: ansible.build.mpw
state: directory
register: _mpw_build_dir
- name: Download MPW source
ansible.builtin.git:
repo: https://gitlab.com/MasterPassword/MasterPassword.git
version: 344771db
recursive: false # does *not* clone submodules
dest: "{{ _mpw_build_dir.path }}"
# God I hate this
- name: Patch .gitmodules to use HTTPS
ansible.builtin.replace:
path: "{{ _mpw_build_dir.path }}/.gitmodules"
regexp: "url = git://"
replace: "url = https://"
- name: Initialize submodules
ansible.builtin.command:
cmd: git submodule update --init
chdir: "{{ _mpw_build_dir.path }}"
- name: Build MasterPassword binary
ansible.builtin.command:
cmd: bash build
chdir: "{{ _mpw_build_dir.path }}/platform-independent/cli-c/"
- name: Copy binary to system path
become: true
ansible.builtin.copy:
remote_src: true
src: "{{ _mpw_build_dir.path }}/platform-independent/cli-c/mpw"
dest: "/usr/local/bin"
mode: 0755
always:
- name: Remove temporary directory
ansible.builtin.file:
path: "{{ _mpw_build_dir.path }}"
state: absent

View File

@@ -0,0 +1,79 @@
---
- name: Check whether binary exists
become: true
ansible.builtin.stat:
path: "~{{ local_username }}/.local/bin/MultiMC"
register: _multimc_stat
- name: Install MultiMC
when: (not _multimc_stat.stat.exists) or (force_reinstall | default(false))
block:
- name: Create temp dir
ansible.builtin.tempfile:
state: directory
register: _multimc_tempdir
- name: Download and unpack distribution archive
ansible.builtin.unarchive:
src: https://files.multimc.org/downloads/mmc-stable-lin64.tar.gz
remote_src: true
dest: "{{ _multimc_tempdir.path }}"
- name: Ensure ~/.local/share/ exists
become: true
ansible.builtin.file:
path: ~{{ local_username }}/.local/share
state: directory
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0700
- name: Ensure ~/.local/bin/ exists
become: true
ansible.builtin.file:
path: ~{{ local_username }}/.local/bin
state: directory
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0700
- name: Copy MMC distribution to ~/.local/share/
become: true
ansible.builtin.copy:
remote_src: true
src: "{{ _multimc_tempdir.path }}/MultiMC/"
dest: "~{{ local_username }}/.local/share/multimc"
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0700
- name: Link MMC binary into ~/.local/bin/
become: true
ansible.builtin.file:
state: link
src: ~{{ local_username }}/.local/share/multimc/MultiMC
path: ~{{ local_username }}/.local/bin/MultiMC
- name: Copy application icon
become: true
ansible.builtin.copy:
src: multimc.png
dest: ~{{ local_username }}/.local/share/icons/multimc.png
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0755
- name: Template application desktop entry
become: true
ansible.builtin.template:
src: multimc.desktop.j2
dest: ~{{ local_username }}/.local/share/applications/multimc.desktop
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0755
always:
- name: Delete temp dir
ansible.builtin.file:
path: "{{ _multimc_tempdir.path }}"
state: absent

View File

@@ -0,0 +1,27 @@
---
- name: Create install directory
become: true
ansible.builtin.file:
path: /opt/pipx
state: directory
owner: "{{ ansible_user }}"
group: "{{ skylab_group_admin.name }}"
mode: 0755
- name: Create install venv
ansible.builtin.command:
cmd: python3 -m venv /opt/pipx
creates: /opt/pipx/bin/python
- name: Install pipx
ansible.builtin.pip:
name:
- pipx
executable: /opt/pipx/bin/pip
- name: Link pipx binary into system path
become: true
ansible.builtin.file:
state: link
src: /opt/pipx/bin/pipx
path: /usr/local/bin/pipx

View File

@@ -0,0 +1 @@
---

Some files were not shown because too many files have changed in this diff Show More