Compare commits

...

68 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
72 changed files with 3782 additions and 953 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,11 +1,10 @@
--- ---
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:

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

2643
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 = "^4.9.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"

View File

@@ -16,4 +16,11 @@ build_ignore: []
# collection label 'namespace.name'. The value is a version range # collection label 'namespace.name'. The value is a version range
# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version # L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version
# range specifiers can be set and are separated by ',' # range specifiers can be set and are separated by ','
dependencies: {} 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

@@ -38,3 +38,10 @@
roles: roles:
- role: skylab.core.dashboard - role: skylab.core.dashboard
dashboard_hostname: "{{ skylab_dashboard }}" dashboard_hostname: "{{ skylab_dashboard }}"
- name: Configure workstations
hosts: workstation
gather_facts: false
roles:
- role: skylab.core.workstation

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

@@ -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

@@ -50,7 +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: update.yaml - import_playbook: skylab.core.update
- import_playbook: configure.yaml - import_playbook: skylab.core.configure

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,14 @@
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
@@ -132,7 +140,7 @@
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 '',
@@ -151,7 +159,11 @@
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: "{{ _active_accounts }}" loop: "{{ _active_accounts }}"
loop_control: loop_control:

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

@@ -18,7 +18,6 @@ skylab_services:
minecraft: minecraft:
user: autocraft 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

View File

@@ -29,7 +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: 300 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 @@
---

View File

@@ -0,0 +1,53 @@
---
- name: Check whether Tor Browser is already installed
become: true
ansible.builtin.stat:
path: "~{{ local_username }}/.local/share/tor-browser/start-tor-browser.desktop"
register: _torbrowser_stat
- name: Install Tor Browser
when: not _torbrowser_stat.stat.exists
block:
- name: Create temp dir
ansible.builtin.tempfile:
state: directory
register: _torbrowser_tempdir
- name: Download and unpack distribution archive
ansible.builtin.unarchive:
src: https://dist.torproject.org/torbrowser/11.0.10/tor-browser-linux64-11.0.10_en-US.tar.xz
remote_src: true
dest: "{{ _torbrowser_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: Copy Tor Browser distribution to ~/.local/share/
become: true
ansible.builtin.copy:
remote_src: true
src: "{{ _torbrowser_tempdir.path }}/tor-browser_en-US/"
dest: "~{{ local_username }}/.local/share/tor-browser"
owner: "{{ local_username }}"
group: "{{ local_username }}"
mode: 0700
- name: Register application
become: true
become_user: "{{ local_username }}"
changed_when: true
ansible.builtin.command:
cmd: ./start-tor-browser.desktop
chdir: ~{{ local_username }}/.local/share/tor-browser
always:
- name: Delete temp dir
ansible.builtin.file:
path: "{{ _torbrowser_tempdir.path }}"
state: absent

View File

@@ -0,0 +1,40 @@
---
- name: Include access vars
ansible.builtin.include_vars:
file: vars/access.yaml
- name: Determine local user accounts
when: skylab_targets | intersect(item.targets | default([]))
vars:
_local_users: []
ansible.builtin.set_fact:
_local_users: "{{ _local_users + [item] }}"
loop: "{{ skylab_accounts }}"
loop_control:
label: "{{ item.name }},{{ item.uid }}"
- name: Determine local human user accounts
when: not (item.service | default(false))
vars:
_local_human_users: []
ansible.builtin.set_fact:
_local_human_users: "{{ _local_human_users + [item.name] }}"
loop: "{{ _local_users }}"
loop_control:
label: "{{ item.name }},{{ item.uid }}"
- name: Determine local admin user accounts
when: item.admin | default(false)
vars:
_local_admin_users: []
ansible.builtin.set_fact:
_local_admin_users: "{{ _local_admin_users + [item.name] }}"
loop: "{{ _local_users }}"
loop_control:
label: "{{ item.name }},{{ item.uid }}"
- name: Install software
ansible.builtin.import_tasks: software.yml
- name: Configure environment
ansible.builtin.import_tasks: environment.yml

View File

@@ -0,0 +1,121 @@
---
- name: Install repositories on Fedora
become: true
when: ansible_distribution == "Fedora"
block:
- name: Install RPMFusion repositories
ansible.builtin.dnf:
name:
- https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-{{ ansible_distribution_major_version }}.noarch.rpm
- https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-{{ ansible_distribution_major_version }}.noarch.rpm
state: present
disable_gpg_check: true
- name: Install Docker CE repository
ansible.builtin.yum_repository:
name: docker-ce-stable
description: Docker CE Stable - $basearch
baseurl: https://download.docker.com/linux/fedora/$releasever/$basearch/stable
enabled: true
gpgcheck: true
gpgkey: https://download.docker.com/linux/fedora/gpg
- name: Install VSCode repository
ansible.builtin.yum_repository:
name: vscode
description: Visual Studio Code
baseurl: https://packages.microsoft.com/yumrepos/vscode
enabled: true
gpgcheck: true
gpgkey: https://packages.microsoft.com/keys/microsoft.asc
- name: Enable Signal-Desktop COPR repository
community.general.copr:
name: luminoso/Signal-Desktop
state: enabled
- name: Install packages on Fedora
become: true
when: ansible_distribution == "Fedora"
ansible.builtin.dnf:
name:
- arc-theme
- cmake
- code # visual studio code
- deluge
- docker-ce
- gcc
- gcc-c++
- gnome-tweaks
- gnome-shell-extension-material-shell
- gnome-shell-extension-openweather
- gnome-shell-extension-system-monitor-applet
- gnome-shell-extension-vertical-overview
- gnupg2
- guvcview
- java-17-openjdk
- jq
- libffi-devel
- libvirt
- libvirt-devel
- libxml2-devel
- mediawriter
- ncurses-devel
- NetworkManager-tui
- pinta
- powerline
- python27
- python36
- python37
- python38
- python39
- python310
- ShellCheck
- signal-desktop
- steam
- systemd-devel
- texlive-fontawesome5
- texlive-roboto
- texlive-scheme-tetex
- texlive-sourcesanspro
- virt-manager
- vlc
- xclip
- yarnpkg
state: present
- name: Install unsigned packages on Fedora
when: ansible_distribution == "Fedora"
become: true
ansible.builtin.dnf:
name:
# draw.io/diagrams.net
- https://github.com/jgraph/drawio-desktop/releases/download/v17.4.2/drawio-x86_64-17.4.2.rpm
# zoom
- https://zoom.us/client/latest/zoom_x86_64.rpm
state: present
disable_gpg_check: true
- ansible.builtin.import_tasks: install_mpw.yml
- ansible.builtin.import_tasks: install_nvm.yml
- ansible.builtin.import_tasks: install_pipx.yml
- ansible.builtin.import_tasks: install_poetry.yml
- ansible.builtin.import_tasks: install_postman.yml
- ansible.builtin.import_tasks: install_rustup.yml
- ansible.builtin.import_tasks: install_typora.yml
# It is now day eight hundred and thirty nine of begging the ansible devs to let
# me loop over blocks. pls bcoca i have a family
- name: Install Tor Browser
ansible.builtin.include_tasks:
file: install_tor_browser.yml
loop: "{{ _local_human_users }}"
loop_control:
loop_var: local_username
- name: Install MultiMC
ansible.builtin.include_tasks:
file: install_multimc.yml
loop: "{{ _local_human_users }}"
loop_control:
loop_var: local_username

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=MultiMC
Comment=Minecraft environment manager
Exec="/home/{{ local_username }}/.local/bin/MultiMC"
Terminal=false
Type=Application
Icon="/home/{{ local_username }}/.local/share/icons/multimc.png"
Categories=Gaming;Graphics;
TryExec="/home/{{ local_username }}/.local/bin/MultiMC"

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

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

16
skylab/infra/galaxy.yml Normal file
View File

@@ -0,0 +1,16 @@
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: []
dependencies:
community.general: ">=6.5.0,<7.0"
ansible.posix: ">=1.5.1,<2.0"

View File

@@ -0,0 +1,2 @@
---
requires_ansible: '>=2.9.10'

View File

@@ -0,0 +1,230 @@
---
- name: Prompt for parameters
hosts: localhost
gather_facts: false
vars_prompt:
- name: bootstrap_hostname
prompt: Enter hostname (or IP address) of bootstrap target
private: false
- name: bootstrap_username
prompt: Enter username to use for connecting to boostrap target
default: root
private: false
- name: bootstrap_password
prompt: Enter password to use for connecting to boostrap target
private: true
default: skylab
- name: bootstrap_port
prompt: Enter SSH port to connect to on bootstrap target
default: 22
private: false
tasks:
- name: Add boostrap host
changed_when: false
ansible.builtin.add_host:
hostname: bootstrap
ansible_host: "{{ bootstrap_hostname }}"
ansible_user: "{{ bootstrap_username }}"
ansible_ssh_pass: "{{ bootstrap_password }}"
ansible_port: "{{ bootstrap_port }}"
- name: Test connection
delegate_to: bootstrap
delegate_facts: true
vars:
ansible_host_key_checking: false
ansible.builtin.ping: {}
- name: Bootstrap remote
hosts: bootstrap
vars:
ansible_host_key_checking: false
vars_prompt:
- name: skylab_ansible_vault_password
prompt: Enter Ansible vault password for generating user secrets
private: true
confirm: true
tasks:
- name: Check OS requirements
ansible.builtin.assert:
that:
- ansible_distribution == 'Rocky'
- ansible_distribution_major_version in ['8', '9']
success_msg: >-
Host is running supported OS {{ ansible_distribution }} {{ ansible_distribution_version }}
fail_msg: >-
Unsupported operating system ({{ ansible_distribution }} {{ ansible_distribution_major_version }}),
only RockyLinux 8 and RockyLinux 9 are supported.
- name: Check that management keys are defined
ansible.builtin.assert:
that:
- skylab_mgmt is defined
- skylab_mgmt.sshkeys != []
success_msg: >-
Found {{ skylab_mgmt.sshkeys | length }} SSH keys to install to the Ansible management user
fail_msg: >-
No management keys were found for installation to the Ansible management user. Aborting to avoid
locking out SSH access to the boostrap host. Please define the 'skylab_mgmt.sshkeys' variable with
a list of SSH public keys to install to the Ansible management user.
- name: Install RockyLinux python bindings
become: true
ansible.builtin.dnf:
state: present
name:
- libffi-devel
- python3-devel
- python3-libselinux
- python3-policycoreutils
- python3-firewall
- name: Create mgmt group
become: true
ansible.builtin.group:
name: "{{ skylab_mgmt.group }}"
state: present
gid: "{{ skylab_mgmt.id }}"
- name: Generate mgmt user account password
delegate_to: localhost
no_log: true
changed_when: false
ansible.builtin.shell:
cmd: >
command mpw -qq -F none -t max -u {{ skylab_mgmt.user }} {{ ansible_host }} -p <<<
'{{ skylab_ansible_vault_password }}' |
python3 -c 'import crypt; print(crypt.crypt(input(), crypt.mksalt(crypt.METHOD_SHA512)))'
executable: /bin/bash
register: _password_mgmt
- name: Update mgmt user account
become: true
ansible.builtin.user:
name: "{{ skylab_mgmt.user }}"
state: present
group: "{{ skylab_mgmt.group }}"
groups:
- "{{ skylab_mgmt.group }}"
- wheel
uid: "{{ skylab_mgmt.id }}"
password: "{{ _password_mgmt.stdout }}"
- name: Update mgmt user authorized keys
become: true
ansible.posix.authorized_key:
user: "{{ skylab_mgmt.user }}"
exclusive: true
key: "{{ skylab_mgmt.sshkeys | join('\n') }}"
- name: Remove mgmt user group
become: true
ansible.builtin.group:
name: "{{ skylab_mgmt.user }}"
state: absent
- name: Update root user authorized keys
become: true
ansible.posix.authorized_key:
user: root
exclusive: true
key: ""
- name: Disable sudo password for WHEEL group
become: true
ansible.builtin.copy:
content: "%wheel ALL=(ALL) NOPASSWD: ALL"
dest: /etc/sudoers.d/30-wheel
owner: root
group: "{{ skylab_mgmt.group }}"
mode: 0644
- name: Disable SSHD password auth
become: true
ansible.builtin.replace:
path: /etc/ssh/sshd_config
regexp: '^(#?)PasswordAuthentication .*$'
replace: PasswordAuthentication no
- name: Disable SSHD root login
become: true
ansible.builtin.replace:
path: /etc/ssh/sshd_config
regexp: '^(#?)PermitRootLogin .*$'
replace: PermitRootLogin no
- name: Update SSHD mgmt port
become: true
ansible.builtin.replace:
path: /etc/ssh/sshd_config
regexp: '^(#?)Port .*$'
replace: Port {{ skylab_mgmt.sshport }}
- name: Grant SSHD permissions on the mgmt port
become: true
community.general.seport:
ports: "{{ skylab_mgmt.sshport }}"
proto: tcp
setype: ssh_port_t
state: present
- name: Install Firewalld
become: true
ansible.builtin.dnf:
name: firewalld
state: present
- name: Enable Firewalld
become: true
ansible.builtin.service:
name: firewalld
enabled: true
- name: Grant SSHD firewall access to the mgmt port
become: true
ansible.posix.firewalld:
port: "{{ skylab_mgmt.sshport }}/tcp"
state: enabled
permanent: true
- name: Revoke SSHD firewall access to default port
become: true
ansible.posix.firewalld:
service: ssh
permanent: true
state: disabled
- name: Update OS
become: true
ansible.builtin.dnf:
name: "*"
state: latest
allowerasing: true
- name: Generate root user account password
delegate_to: localhost
no_log: true
changed_when: false
ansible.builtin.shell:
cmd: >
command mpw -qq -F none -t max -u root {{ ansible_host }} -p <<<
'{{ skylab_ansible_vault_password }}' |
python3 -c 'import crypt; print(crypt.crypt(input(), crypt.mksalt(crypt.METHOD_SHA512)))'
executable: /bin/bash
register: _password_root
- name: Update root user account
become: true
ansible.builtin.user:
name: root
state: present
password: "{{ _password_root.stdout }}"
- name: Create SkyLab directory
become: true
ansible.builtin.file:
state: directory
path: "{{ skylab_state_dir }}"
owner: "{{ skylab_mgmt.user }}"
group: "{{ skylab_mgmt.group }}"
mode: 0750

View File

@@ -0,0 +1,46 @@
---
- name: Provision DigitalOcean cloud
hosts: localhost
vars:
terraform_backend: "postgres://{{ skylab_tfstate_backend.username }}:{{ skylab_tfstate_backend.password }}@{{ skylab_tfstate_backend.hostname }}:{{ skylab_tfstate_backend.port }}/{{ skylab_tfstate_backend.schema }}"
tasks:
- name: Deploy terraform config
block:
- name: Create temp plan file
changed_when: false
ansible.builtin.tempfile:
state: file
prefix: skylab
suffix: tfplan
register: _tfplan_tempfile
# Generating a plan file before yeeting a deployment into the
# wind helps to ensure that the syntax is correct, backend and
# state are valid, and all the plumbing is working as expected.
# We don't want errors when we deploy, so it's better to
# generate the plan first
- name: Initialize terraform backend and generate plan file
community.general.terraform:
state: planned
project_path: terraform/
backend_config:
conn_str: "{{ terraform_backend }}"
force_init: true
init_reconfigure: true
plan_file: "{{ _tfplan_tempfile.path }}"
# TODO: update to take DO token from invocation args rather than
# implicit env var
- name: Apply terraform plan
community.general.terraform:
state: present
project_path: terraform/
backend_config:
conn_str: "{{ terraform_backend }}"
plan_file: "{{ _tfplan_tempfile.path }}"
always:
- name: Remove temp plan file
changed_when: false
ansible.builtin.file:
path: "{{ _tfplan_tempfile.path }}"
state: absent

View File

@@ -0,0 +1,57 @@
resource "digitalocean_domain" "allaroundhere" {
name = "allaroundhere.org"
}
# ==========================================================================
# Standard hostname configuration
resource "digitalocean_record" "allaroundhere" {
domain = digitalocean_domain.allaroundhere.id
type = "A"
name = "@"
value = "24.2.156.189"
ttl = 3600
}
resource "digitalocean_record" "allaroundhere_www" {
domain = digitalocean_domain.allaroundhere.id
type = "CNAME"
name = "www"
value = "@"
ttl = 43200
}
resource "digitalocean_record" "allaroundhere_content" {
domain = digitalocean_domain.allaroundhere.id
type = "CNAME"
name = "content"
value = "en1.enp.one."
ttl = 10300
}
# ==========================================================================
# Standard DO configuration for all managed domains, includes
# NS records and SOA
resource "digitalocean_record" "allaroundhere_ns1" {
domain = digitalocean_domain.allaroundhere.id
type = "NS"
name = "@"
value = "ns1.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "allaroundhere_ns2" {
domain = digitalocean_domain.allaroundhere.id
type = "NS"
name = "@"
value = "ns2.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "allaroundhere_ns3" {
domain = digitalocean_domain.allaroundhere.id
type = "NS"
name = "@"
value = "ns3.digitalocean.com."
ttl = 1800
}

View File

@@ -0,0 +1,200 @@
resource "digitalocean_domain" "enp" {
name = "enp.one"
}
# ==========================================================================
# Standard hostname configuration
resource "digitalocean_record" "enp" {
domain = digitalocean_domain.enp.id
type = "A"
name = "@"
value = "24.2.156.189"
ttl = 3600
}
resource "digitalocean_record" "enp_en1" {
domain = digitalocean_domain.enp.id
type = "A"
name = "en1"
value = digitalocean_record.enp.value
ttl = 3600
}
# ==========================================================================
# Service CNAME configuration
resource "digitalocean_record" "enp_vcs" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "vcs"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_ssv" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "ssv"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_pms" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "pms"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_cdn" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "cdn"
value = "${digitalocean_cdn.enp.endpoint}."
ttl = 3600
}
resource "digitalocean_record" "enp_vpn" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "vpn"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_www" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "www"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_sso" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "sso"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
resource "digitalocean_record" "enp_img" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "img"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 10600
}
# ==========================================================================
# Standard DO configuration for all managed domains, includes
# NS records and SOA
resource "digitalocean_record" "enp_ns1" {
domain = digitalocean_domain.enp.id
type = "NS"
name = "@"
value = "ns1.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "enp_ns2" {
domain = digitalocean_domain.enp.id
type = "NS"
name = "@"
value = "ns2.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "enp_ns3" {
domain = digitalocean_domain.enp.id
type = "NS"
name = "@"
value = "ns3.digitalocean.com."
ttl = 1800
}
# ==========================================================================
# DMARC and HTTPS security configuration
resource "digitalocean_record" "enp_dmarc" {
domain = digitalocean_domain.enp.id
type = "TXT"
name = "_dmarc"
value = "v=DMARC1; p=quarantine; adkim=s"
ttl = 3600
}
resource "digitalocean_record" "enp_caa" {
domain = digitalocean_domain.enp.id
type = "CAA"
name = "@"
value = "letsencrypt.org."
ttl = 3600
tag = "issue"
flags = 0
}
resource "digitalocean_record" "enp_iodef" {
domain = digitalocean_domain.enp.id
type = "CAA"
name = "@"
value = "mailto:admin@enp.one"
ttl = 3600
tag = "iodef"
flags = 0
}
# ==========================================================================
# Tutanota mailer integration configuration
resource "digitalocean_record" "enp_mx" {
domain = digitalocean_domain.enp.id
type = "MX"
name = "@"
value = "mail.tutanota.de."
ttl = 3600
priority = 1010
}
resource "digitalocean_record" "enp_spf" {
domain = digitalocean_domain.enp.id
type = "TXT"
name = "@"
value = "v=spf1 include:spf.tutanota.de -all"
ttl = 3600
}
resource "digitalocean_record" "enp_domainkey1" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "s1._domainkey"
value = "s1._domainkey.tutanota.de."
ttl = 10600
}
resource "digitalocean_record" "enp_domainkey2" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "s2._domainkey"
value = "s2._domainkey.tutanota.de."
ttl = 10600
}
resource "digitalocean_record" "enp_mta1" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "_mta-sts"
value = "_mta-sts.tutanota.com."
ttl = 10600
}
resource "digitalocean_record" "enp_mta2" {
domain = digitalocean_domain.enp.id
type = "CNAME"
name = "mta-sts"
value = "mta-sts.tutanota.com."
ttl = 10600
}

View File

@@ -0,0 +1,123 @@
resource "digitalocean_domain" "enpaul" {
name = "enpaul.net"
}
# ==========================================================================
# Standard hostname configuration
resource "digitalocean_record" "enpaul" {
domain = digitalocean_domain.enpaul.id
type = "A"
name = "@"
value = digitalocean_record.enp.value
ttl = 3600
}
resource "digitalocean_record" "enpaul_www" {
domain = digitalocean_domain.enpaul.id
type = "CNAME"
name = "www"
value = "@"
ttl = 10800
}
# ==========================================================================
# Standard DO configuration for all managed domains, includes
# NS records and SOA
resource "digitalocean_record" "enpaul_ns1" {
domain = digitalocean_domain.enpaul.id
type = "NS"
name = "@"
value = "ns1.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "enpaul_ns2" {
domain = digitalocean_domain.enpaul.id
type = "NS"
name = "@"
value = "ns2.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "enpaul_ns3" {
domain = digitalocean_domain.enpaul.id
type = "NS"
name = "@"
value = "ns3.digitalocean.com."
ttl = 1800
}
# ==========================================================================
# DMARC and HTTPS security configuration
resource "digitalocean_record" "enpaul_dmarc" {
domain = digitalocean_domain.enpaul.id
type = "TXT"
name = "_dmarc"
value = "v=DMARC1; p=quarantine; adkim=s"
ttl = 3600
}
resource "digitalocean_record" "enpaul_caa" {
domain = digitalocean_domain.enpaul.id
type = "CAA"
name = "@"
value = "letsencrypt.org."
ttl = 3600
tag = "issue"
flags = 0
}
# ==========================================================================
# Tutanota mailer integration configuration
resource "digitalocean_record" "enpaul_mx" {
domain = digitalocean_domain.enpaul.id
type = "MX"
name = "@"
value = "mail.tutanota.de."
ttl = 3600
priority = 10
}
resource "digitalocean_record" "enpaul_spf" {
domain = digitalocean_domain.enpaul.id
type = "TXT"
name = "@"
value = "v=spf1 include:spf.tutanota.de -all"
ttl = 3600
}
resource "digitalocean_record" "enpaul_domainkey1" {
domain = digitalocean_domain.enpaul.id
type = "CNAME"
name = "s1._domainkey"
value = "s1._domainkey.tutanota.de."
ttl = 10600
}
resource "digitalocean_record" "enpaul_domainkey2" {
domain = digitalocean_domain.enpaul.id
type = "CNAME"
name = "s2._domainkey"
value = "s2._domainkey.tutanota.de."
ttl = 10600
}
resource "digitalocean_record" "enpaul_mta1" {
domain = digitalocean_domain.enpaul.id
type = "CNAME"
name = "_mta-sts"
value = "_mta-sts.tutanota.com."
ttl = 10600
}
resource "digitalocean_record" "enpaul_mta2" {
domain = digitalocean_domain.enpaul.id
type = "CNAME"
name = "mta-sts"
value = "mta-sts.tutanota.com."
ttl = 10600
}

View File

@@ -0,0 +1,72 @@
resource "digitalocean_domain" "scipiocapital" {
name = "scipiocapital.us"
}
# ==========================================================================
# Standard hostname configuration
resource "digitalocean_record" "scipiocapital" {
domain = digitalocean_domain.scipiocapital.id
type = "A"
name = "@"
value = digitalocean_record.enp.value
ttl = 3600
}
resource "digitalocean_record" "scipiocapital_app" {
domain = digitalocean_domain.scipiocapital.id
type = "CNAME"
name = "app"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 43200
}
resource "digitalocean_record" "scipiocapital_notify" {
domain = digitalocean_domain.scipiocapital.id
type = "CNAME"
name = "notify"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 43200
}
resource "digitalocean_record" "scipiocapital_docs" {
domain = digitalocean_domain.scipiocapital.id
type = "CNAME"
name = "docs"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 43200
}
resource "digitalocean_record" "scipiocapital_auth" {
domain = digitalocean_domain.scipiocapital.id
type = "CNAME"
name = "auth"
value = "${digitalocean_record.enp_en1.fqdn}."
ttl = 43200
}
# ==========================================================================
# Standard DO configuration for all managed domains, includes
# NS records and SOA
resource "digitalocean_record" "scipiocapital_ns1" {
domain = digitalocean_domain.scipiocapital.id
type = "NS"
name = "@"
value = "ns1.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "scipiocapital_ns2" {
domain = digitalocean_domain.scipiocapital.id
type = "NS"
name = "@"
value = "ns2.digitalocean.com."
ttl = 1800
}
resource "digitalocean_record" "scipiocapital_ns3" {
domain = digitalocean_domain.scipiocapital.id
type = "NS"
name = "@"
value = "ns3.digitalocean.com."
ttl = 1800
}

View File

@@ -0,0 +1,10 @@
terraform {
backend "pg" {}
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
}

View File

@@ -0,0 +1,13 @@
resource "digitalocean_project" "scipio" {
name = "Scipio Capital"
description = "Eventual home of Scipio Capital systems"
purpose = "Service or API"
environment = "Production"
}
resource "digitalocean_project_resources" "scipio" {
project = digitalocean_project.scipio.id
resources = [
digitalocean_domain.scipiocapital.urn,
]
}

View File

@@ -0,0 +1,17 @@
resource "digitalocean_project" "skylab" {
name = "SkyLab"
description = "SkyLab resources, with emphasis on Sky"
purpose = "Operational / Developer tooling"
environment = "Development"
is_default = true
}
resource "digitalocean_project_resources" "skylab" {
project = digitalocean_project.skylab.id
resources = [
digitalocean_domain.allaroundhere.urn,
digitalocean_domain.enpaul.urn,
digitalocean_domain.enp.urn,
digitalocean_spaces_bucket.enp_cdn.urn
]
}

View File

@@ -0,0 +1,18 @@
resource "digitalocean_spaces_bucket" "enp_cdn" {
name = "en2-cdn"
region = "nyc3"
acl = "public-read"
force_destroy = false
}
resource "digitalocean_certificate" "enp_cdn" {
name = "CDN"
type = "lets_encrypt"
domains = ["cdn.enp.one", "enp.one"]
}
resource "digitalocean_cdn" "enp" {
origin = digitalocean_spaces_bucket.enp_cdn.bucket_domain_name
custom_domain = "cdn.enp.one"
certificate_name = digitalocean_certificate.enp_cdn.name
}

44
tox.ini Normal file
View File

@@ -0,0 +1,44 @@
[tox]
envlist = ansible, security
skipsdist = true
[testenv]
require_locked_deps = true
require_poetry = true
setenv =
ANSIBLE_CONFIG = {toxinidir}/ansible.cfg
whitelist_externals =
bash
[testenv:ansible]
description = Lint ansible resources
locked_deps =
ansible-core
ansible-lint
yamllint
pre-commit
pre-commit-hooks
mdformat
mdformat-gfm
commands =
yamllint --config-file {toxinidir}/.yamllintrc.yaml \
{toxinidir}/skylab/ \
{toxinidir}/inventory.yaml \
{toxinidir}/requirements.yaml
bash -c "ansible-lint -c {toxinidir}/.ansible-lint.yaml \
{toxinidir}/skylab/*/playbooks/"
pre-commit run --all-files
[testenv:security]
description = Check security parameters
ignore_errors = true
locked_deps =
poetry
safety
commands =
poetry export --format requirements.txt --without-hashes --with dev --output {envtmpdir}/req.txt
safety check --output text --file {envtmpdir}/req.txt \
# Ignore unfixed CVE-2021-3532 from ansible \
--ignore 42923 \
# https://github.com/pytest-dev/py/issues/287#issuecomment-1283567565
--ignore 51457