ctucx.git: ansible-configs

My personal ansible roles and playbooks [deprecated in favor of nixos]

commit 9f3537b4bf6932533d318a48362cff4e39380693
Author: ctucx <c@ctu.cx>
Date: Sat, 17 Oct 2020 17:35:41 +0200

initial commit
64 files changed, 3139 insertions(+), 0 deletions(-)
A
.gitignore
|
1
+
A
config-files/acme-redirect/acme-redirect.conf
|
3
+++
A
config-files/awall/custom-services.json
|
7
+++++++
A
config-files/awall/dns.json
|
13
+++++++++++++
A
config-files/awall/mail.json
|
37
+++++++++++++++++++++++++++++++++++++
A
config-files/awall/ssh.json
|
14
++++++++++++++
A
config-files/awall/syncthing.json
|
19
+++++++++++++++++++
A
config-files/awall/web.json
|
19
+++++++++++++++++++
A
config-files/cgit/cgit.css
|
987
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/cgit/cgitrc
|
42
++++++++++++++++++++++++++++++++++++++++++
A
config-files/gitolite/gitolite.rc.patch
|
11
+++++++++++
A
config-files/nginx/nginx.conf
|
52
++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/nginx/ssl.conf
|
21
+++++++++++++++++++++
A
config-files/pleroma/config.exs
|
104
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/prometheus/prometheus.yml
|
39
+++++++++++++++++++++++++++++++++++++++
A
config-files/radicale/config
|
48
++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/riot-web/config.json
|
55
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/ssh/sshd_config.patch
|
29
+++++++++++++++++++++++++++++
A
config-files/sudo/sudoers.patch
|
11
+++++++++++
A
config-files/synapse/homeserver.yaml
|
88
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config-files/synapse/log.yaml
|
39
+++++++++++++++++++++++++++++++++++++++
A
config-files/syncthing/syncthing.initd
|
20
++++++++++++++++++++
A
config-files/website-vhosts/ctu.cx.conf
|
26
++++++++++++++++++++++++++
A
config-files/website-vhosts/photos.ctu.cx.conf
|
20
++++++++++++++++++++
A
inventory
|
9
+++++++++
A
playbooks.yml
|
201
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/acme-redirect/tasks/main.yml
|
56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/acme-redirect/templates/acme-redirect.conf.j2
|
12
++++++++++++
A
roles/bind/tasks/main.yml
|
48
++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/bind/templates/named.conf.j2
|
32
++++++++++++++++++++++++++++++++
A
roles/cgit/tasks/main.yml
|
53
+++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/cgit/templates/cgit-vhost.conf.j2
|
21
+++++++++++++++++++++
A
roles/common/handlers/main.yml
|
3
+++
A
roles/common/tasks/firewall.yml
|
40
++++++++++++++++++++++++++++++++++++++++
A
roles/common/tasks/main.yml
|
14
++++++++++++++
A
roles/common/tasks/network.yml
|
30
++++++++++++++++++++++++++++++
A
roles/common/tasks/node-exporter.yml
|
9
+++++++++
A
roles/common/tasks/packages.yml
|
30
++++++++++++++++++++++++++++++
A
roles/common/tasks/sshd.yml
|
12
++++++++++++
A
roles/common/tasks/sudo.yml
|
12
++++++++++++
A
roles/common/tasks/users.yml
|
33
+++++++++++++++++++++++++++++++++
A
roles/common/templates/awall-baseconfig.json.j2
|
28
++++++++++++++++++++++++++++
A
roles/common/templates/hosts.conf.j2
|
2
++
A
roles/common/templates/interfaces.conf.j2
|
16
++++++++++++++++
A
roles/common/templates/resolv.conf.j2
|
4
++++
A
roles/gitolite/tasks/main.yml
|
58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/maddy/tasks/main.yml
|
37
+++++++++++++++++++++++++++++++++++++
A
roles/maddy/templates/maddy.conf.j2
|
182
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/nginx/tasks/main.yml
|
59
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/nginx/templates/vhost.conf.j2
|
22
++++++++++++++++++++++
A
roles/oeffisearch/tasks/main.yml
|
25
+++++++++++++++++++++++++
A
roles/oeffisearch/templates/oeffisearch-vhost.conf.j2
|
19
+++++++++++++++++++
A
roles/pleroma/tasks/main.yml
|
71
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/prometheus/tasks/main.yml
|
39
+++++++++++++++++++++++++++++++++++++++
A
roles/prometheus/templates/prometheus-vhost.conf.j2
|
19
+++++++++++++++++++
A
roles/radicale/tasks/main.yml
|
40
++++++++++++++++++++++++++++++++++++++++
A
roles/radicale/templates/radicale-vhost.conf.j2
|
18
++++++++++++++++++
A
roles/synapse/tasks/main.yml
|
51
+++++++++++++++++++++++++++++++++++++++++++++++++++
A
roles/synapse/templates/synapse-vhost.conf.j2
|
20
++++++++++++++++++++
A
roles/syncthing/tasks/main.yml
|
41
+++++++++++++++++++++++++++++++++++++++++
A
roles/syncthing/templates/syncthing-vhost.conf.j2
|
16
++++++++++++++++
A
roles/websites/tasks/ctu.cx.yml
|
21
+++++++++++++++++++++
A
roles/websites/tasks/main.yml
|
10
++++++++++
A
roles/websites/tasks/photos.ctu.cx.yml
|
21
+++++++++++++++++++++
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+secrets/
diff --git a/config-files/acme-redirect/acme-redirect.conf b/config-files/acme-redirect/acme-redirect.conf
@@ -0,0 +1,3 @@
+[acme]
+acme_email = "lets-encrypt@ctu.cx"
+acme_url   = "https://api.buypass.com/acme/directory"
diff --git a/config-files/awall/custom-services.json b/config-files/awall/custom-services.json
@@ -0,0 +1,7 @@
+{
+	"service": {
+		"submissions": [
+			{ "proto": "tcp", "port": 465 }
+		]
+	}
+}
diff --git a/config-files/awall/dns.json b/config-files/awall/dns.json
@@ -0,0 +1,13 @@
+{
+  "description": "Allow DNS on WAN",
+  "import": [ "base" ],
+
+  "filter": [
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "dns",
+      "action": "accept"
+    }
+  ]
+}
diff --git a/config-files/awall/mail.json b/config-files/awall/mail.json
@@ -0,0 +1,37 @@
+{
+  "description": "Allow mail specific ports on WAN",
+  "import": [ "base" ],
+
+  "filter": [
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "smtp",
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "submissions",
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "submission",
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "imap",
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "imaps",
+      "action": "accept"
+    }
+  ]
+}
diff --git a/config-files/awall/ssh.json b/config-files/awall/ssh.json
@@ -0,0 +1,14 @@
+{
+  "description": "Allow rate-limited SSH on WAN",
+  "import": [ "base" ],
+
+  "filter": [
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "ssh",
+      "action": "accept",
+      "conn-limit": { "count": 3, "interval": 20 }
+    }
+  ]
+}
diff --git a/config-files/awall/syncthing.json b/config-files/awall/syncthing.json
@@ -0,0 +1,19 @@
+{
+  "description": "Allow syncthing specific ports on WAN",
+  "import": [ "base" ],
+
+  "filter": [
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": {"proto": "tcp", "port": 22000},
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": {"proto": "udp", "port": 21027},
+      "action": "accept"
+    }
+  ]
+}
diff --git a/config-files/awall/web.json b/config-files/awall/web.json
@@ -0,0 +1,19 @@
+{
+  "description": "Allow HTTP(S) on WAN",
+  "import": [ "base" ],
+
+  "filter": [
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "http",
+      "action": "accept"
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "https",
+      "action": "accept"
+    }
+  ]
+}
diff --git a/config-files/cgit/cgit.css b/config-files/cgit/cgit.css
@@ -0,0 +1,987 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * See <https://www.gnu.org/licenses/>.
+ */
+
+div#cgit {
+	padding: 0em;
+	margin: 0em;
+	font-family: sans-serif;
+	font-size: 10pt;
+	color: #333;
+	background: white;
+	padding: 4px;
+}
+
+div#cgit a {
+	color: blue;
+	text-decoration: none;
+}
+
+div#cgit a:hover {
+	text-decoration: underline;
+}
+
+div#cgit table {
+	border-collapse: collapse;
+}
+
+div#cgit table#header {
+	width: 100%;
+	margin-bottom: 1em;
+}
+
+div#cgit table#header td.logo {
+	width: 96px;
+	vertical-align: top;
+}
+
+div#cgit table#header td.main {
+	font-size: 250%;
+	padding-left: 10px;
+	white-space: nowrap;
+}
+
+div#cgit table#header td.main a {
+	color: #000;
+}
+
+div#cgit table#header td.form {
+	text-align: right;
+	vertical-align: bottom;
+	padding-right: 1em;
+	padding-bottom: 2px;
+	white-space: nowrap;
+}
+
+div#cgit table#header td.form form,
+div#cgit table#header td.form input,
+div#cgit table#header td.form select {
+	font-size: 90%;
+}
+
+div#cgit table#header td.sub {
+	color: #777;
+	border-top: solid 1px #ccc;
+	padding-left: 10px;
+}
+
+div#cgit table.tabs {
+	border-bottom: solid 3px #ccc;
+	border-collapse: collapse;
+	margin-top: 2em;
+	margin-bottom: 0px;
+	width: 100%;
+}
+
+div#cgit table.tabs td {
+	padding: 0px 1em;
+	vertical-align: bottom;
+}
+
+div#cgit table.tabs td a {
+	padding: 2px 0.75em;
+	color: #777;
+	font-size: 110%;
+}
+
+div#cgit table.tabs td a.active {
+	color: #000;
+	background-color: #ccc;
+}
+
+div#cgit table.tabs a[href^="http://"]:after, div#cgit table.tabs a[href^="https://"]:after {
+	content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgAhcJDQY+gm2TAAAAHWlUWHRDb21tZW50AAAAAABDcmVhdGVkIHdpdGggR0lNUGQuZQcAAABbSURBVAhbY2BABs4MU4CwhYHBh2Erww4wrGFQZHjI8B8IgUIscJWyDHcggltQhI4zGDCcRwhChPggHIggP1QoAVmQkSETrGoHsiAEsACtBYN0oDAMbgU6EBcAAL2eHUt4XUU4AAAAAElFTkSuQmCC);
+	opacity: 0.5;
+	margin: 0 0 0 5px;
+}
+
+div#cgit table.tabs td.form {
+	text-align: right;
+}
+
+div#cgit table.tabs td.form form {
+	padding-bottom: 2px;
+	font-size: 90%;
+	white-space: nowrap;
+}
+
+div#cgit table.tabs td.form input,
+div#cgit table.tabs td.form select {
+	font-size: 90%;
+}
+
+div#cgit div.path {
+	margin: 0px;
+	padding: 5px 2em 2px 2em;
+	color: #000;
+	background-color: #eee;
+}
+
+div#cgit div.content {
+	margin: 0px;
+	padding: 2em;
+	border-bottom: solid 3px #ccc;
+}
+
+
+div#cgit table.list {
+	width: 100%;
+	border: none;
+	border-collapse: collapse;
+}
+
+div#cgit table.list tr {
+	background: white;
+}
+
+div#cgit table.list tr.logheader {
+	background: #eee;
+}
+
+div#cgit table.list tr:nth-child(even) {
+	background: #f7f7f7;
+}
+
+div#cgit table.list tr:nth-child(odd) {
+	background: white;
+}
+
+div#cgit table.list tr:hover {
+	background: #eee;
+}
+
+div#cgit table.list tr.nohover {
+	background: white;
+}
+
+div#cgit table.list tr.nohover:hover {
+	background: white;
+}
+
+div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+	background: #f7f7f7;
+}
+
+div#cgit table.list tr.nohover-highlight:hover:nth-child(odd) {
+	background: white;
+}
+
+div#cgit table.list th {
+	font-weight: bold;
+	/* color: #888;
+	border-top: dashed 1px #888;
+	border-bottom: dashed 1px #888;
+	*/
+	padding: 0.1em 0.5em 0.05em 0.5em;
+	vertical-align: baseline;
+}
+
+div#cgit table.list td {
+	border: none;
+	padding: 0.1em 0.5em 0.1em 0.5em;
+}
+
+div#cgit table.list td.commitgraph {
+	font-family: monospace;
+	white-space: pre;
+}
+
+div#cgit table.list td.commitgraph .column1 {
+	color: #a00;
+}
+
+div#cgit table.list td.commitgraph .column2 {
+	color: #0a0;
+}
+
+div#cgit table.list td.commitgraph .column3 {
+	color: #aa0;
+}
+
+div#cgit table.list td.commitgraph .column4 {
+	color: #00a;
+}
+
+div#cgit table.list td.commitgraph .column5 {
+	color: #a0a;
+}
+
+div#cgit table.list td.commitgraph .column6 {
+	color: #0aa;
+}
+
+div#cgit table.list td.logsubject {
+	font-family: monospace;
+	font-weight: bold;
+}
+
+div#cgit table.list td.logmsg {
+	font-family: monospace;
+	white-space: pre;
+	padding: 0 0.5em;
+}
+
+div#cgit table.list td a {
+	color: black;
+}
+
+div#cgit table.list td a.ls-dir {
+	font-weight: bold;
+	color: #00f;
+}
+
+div#cgit table.list td a:hover {
+	color: #00f;
+}
+
+div#cgit img {
+	border: none;
+}
+
+div#cgit input#switch-btn {
+	margin: 2px 0px 0px 0px;
+}
+
+div#cgit td#sidebar input.txt {
+	width: 100%;
+	margin: 2px 0px 0px 0px;
+}
+
+div#cgit table#grid {
+	margin: 0px;
+}
+
+div#cgit td#content {
+	vertical-align: top;
+	padding: 1em 2em 1em 1em;
+	border: none;
+}
+
+div#cgit div#summary {
+	vertical-align: top;
+	margin-bottom: 1em;
+        max-width: 70ch;
+}
+
+div#cgit table#downloads {
+	float: right;
+	border-collapse: collapse;
+	border: solid 1px #777;
+	margin-left: 0.5em;
+	margin-bottom: 0.5em;
+}
+
+div#cgit table#downloads th {
+	background-color: #ccc;
+}
+
+div#cgit div#blob {
+	border: solid 1px black;
+}
+
+div#cgit div.error {
+	color: red;
+	font-weight: bold;
+	margin: 1em 2em;
+}
+
+div#cgit a.ls-blob, div#cgit a.ls-dir, div#cgit .ls-mod {
+	font-family: monospace;
+}
+
+div#cgit td.ls-size {
+	text-align: right;
+	font-family: monospace;
+	width: 10em;
+}
+
+div#cgit td.ls-mode {
+	font-family: monospace;
+	width: 10em;
+}
+
+div#cgit table.blob {
+	margin-top: 0.5em;
+	border-top: solid 1px black;
+}
+
+div#cgit table.blob td.hashes,
+div#cgit table.blob td.lines {
+	margin: 0; padding: 0 0 0 0.5em;
+	vertical-align: top;
+	color: black;
+}
+
+div#cgit table.blob td.linenumbers {
+	margin: 0; padding: 0 0.5em 0 0.5em;
+	vertical-align: top;
+	text-align: right;
+	border-right: 1px solid gray;
+}
+
+div#cgit table.blob pre {
+	padding: 0; margin: 0;
+}
+
+div#cgit table.blob td.linenumbers a,
+div#cgit table.ssdiff td.lineno a {
+	color: gray;
+	text-align: right;
+	text-decoration: none;
+}
+
+div#cgit table.blob td.linenumbers a:hover,
+div#cgit table.ssdiff td.lineno a:hover {
+	color: black;
+}
+
+div#cgit table.blame td.hashes,
+div#cgit table.blame td.lines,
+div#cgit table.blame td.linenumbers {
+	padding: 0;
+}
+
+div#cgit table.blame td.hashes div.alt,
+div#cgit table.blame td.lines div.alt {
+	padding: 0 0.5em 0 0.5em;
+}
+
+div#cgit table.blame td.linenumbers div.alt {
+	padding: 0 0.5em 0 0;
+}
+
+div#cgit table.blame div.alt:nth-child(even) {
+	background: #eee;
+}
+
+div#cgit table.blame div.alt:nth-child(odd) {
+	background: white;
+}
+
+div#cgit table.blame td.lines > div {
+	position: relative;
+}
+
+div#cgit table.blame td.lines > div > pre {
+	padding: 0 0 0 0.5em;
+	position: absolute;
+	top: 0;
+}
+
+div#cgit table.bin-blob {
+	margin-top: 0.5em;
+	border: solid 1px black;
+}
+
+div#cgit table.bin-blob th {
+	font-family: monospace;
+	white-space: pre;
+	border: solid 1px #777;
+	padding: 0.5em 1em;
+}
+
+div#cgit table.bin-blob td {
+	font-family: monospace;
+	white-space: pre;
+	border-left: solid 1px #777;
+	padding: 0em 1em;
+}
+
+div#cgit table.nowrap td {
+	white-space: nowrap;
+}
+
+div#cgit table.commit-info {
+	border-collapse: collapse;
+	margin-top: 1.5em;
+}
+
+div#cgit div.cgit-panel {
+	float: right;
+	margin-top: 1.5em;
+}
+
+div#cgit div.cgit-panel table {
+	border-collapse: collapse;
+	border: solid 1px #aaa;
+	background-color: #eee;
+}
+
+div#cgit div.cgit-panel th {
+	text-align: center;
+}
+
+div#cgit div.cgit-panel td {
+	padding: 0.25em 0.5em;
+}
+
+div#cgit div.cgit-panel td.label {
+	padding-right: 0.5em;
+}
+
+div#cgit div.cgit-panel td.ctrl {
+	padding-left: 0.5em;
+}
+
+div#cgit table.commit-info th {
+	text-align: left;
+	font-weight: normal;
+	padding: 0.1em 1em 0.1em 0.1em;
+	vertical-align: top;
+}
+
+div#cgit table.commit-info td {
+	font-weight: normal;
+	padding: 0.1em 1em 0.1em 0.1em;
+}
+
+div#cgit div.commit-subject {
+	font-weight: bold;
+	font-size: 125%;
+	margin: 1.5em 0em 0.5em 0em;
+	padding: 0em;
+}
+
+div#cgit div.commit-msg {
+	white-space: pre;
+	font-family: monospace;
+}
+
+div#cgit div.notes-header {
+	font-weight: bold;
+	padding-top: 1.5em;
+}
+
+div#cgit div.notes {
+	white-space: pre;
+	font-family: monospace;
+	border: solid 1px #ee9;
+	background-color: #ffd;
+	padding: 0.3em 2em 0.3em 1em;
+	float: left;
+}
+
+div#cgit div.notes-footer {
+	clear: left;
+}
+
+div#cgit div.diffstat-header {
+	font-weight: bold;
+	padding-top: 1.5em;
+}
+
+div#cgit table.diffstat {
+	border-collapse: collapse;
+	border: solid 1px #aaa;
+	background-color: #eee;
+}
+
+div#cgit table.diffstat th {
+	font-weight: normal;
+	text-align: left;
+	text-decoration: underline;
+	padding: 0.1em 1em 0.1em 0.1em;
+	font-size: 100%;
+}
+
+div#cgit table.diffstat td {
+	padding: 0.2em 0.2em 0.1em 0.1em;
+	font-size: 100%;
+	border: none;
+}
+
+div#cgit table.diffstat td.mode {
+	white-space: nowrap;
+}
+
+div#cgit table.diffstat td span.modechange {
+	padding-left: 1em;
+	color: red;
+}
+
+div#cgit table.diffstat td.add a {
+	color: green;
+}
+
+div#cgit table.diffstat td.del a {
+	color: red;
+}
+
+div#cgit table.diffstat td.upd a {
+	color: blue;
+}
+
+div#cgit table.diffstat td.graph {
+	width: 500px;
+	vertical-align: middle;
+}
+
+div#cgit table.diffstat td.graph table {
+	border: none;
+}
+
+div#cgit table.diffstat td.graph td {
+	padding: 0px;
+	border: 0px;
+	height: 7pt;
+}
+
+div#cgit table.diffstat td.graph td.add {
+	background-color: #5c5;
+}
+
+div#cgit table.diffstat td.graph td.rem {
+	background-color: #c55;
+}
+
+div#cgit div.diffstat-summary {
+	color: #888;
+	padding-top: 0.5em;
+}
+
+div#cgit table.diff {
+	width: 100%;
+}
+
+div#cgit table.diff td {
+	font-family: monospace;
+	white-space: pre;
+}
+
+div#cgit table.diff td div.head {
+	font-weight: bold;
+	margin-top: 1em;
+	color: black;
+}
+
+div#cgit table.diff td div.hunk {
+	color: #009;
+}
+
+div#cgit table.diff td div.add {
+	color: green;
+}
+
+div#cgit table.diff td div.del {
+	color: red;
+}
+
+div#cgit .sha1 {
+	font-family: monospace;
+	font-size: 90%;
+}
+
+div#cgit .left {
+	text-align: left;
+}
+
+div#cgit .right {
+	text-align: right;
+}
+
+div#cgit table.list td.reposection {
+	font-style: italic;
+	color: #888;
+}
+
+div#cgit a.button {
+	font-size: 80%;
+	padding: 0em 0.5em;
+}
+
+div#cgit a.primary {
+	font-size: 100%;
+}
+
+div#cgit a.secondary {
+	font-size: 90%;
+}
+
+div#cgit td.toplevel-repo {
+
+}
+
+div#cgit table.list td.sublevel-repo {
+	padding-left: 1.5em;
+}
+
+div#cgit ul.pager {
+	list-style-type: none;
+	text-align: center;
+	margin: 1em 0em 0em 0em;
+	padding: 0;
+}
+
+div#cgit ul.pager li {
+	display: inline-block;
+	margin: 0.25em 0.5em;
+}
+
+div#cgit ul.pager a {
+	color: #777;
+}
+
+div#cgit ul.pager .current {
+	font-weight: bold;
+}
+
+div#cgit span.age-mins {
+	font-weight: bold;
+	color: #080;
+}
+
+div#cgit span.age-hours {
+	color: #080;
+}
+
+div#cgit span.age-days {
+	color: #040;
+}
+
+div#cgit span.age-weeks {
+	color: #444;
+}
+
+div#cgit span.age-months {
+	color: #888;
+}
+
+div#cgit span.age-years {
+	color: #bbb;
+}
+
+div#cgit span.insertions {
+	color: #080;
+}
+
+div#cgit span.deletions {
+	color: #800;
+}
+
+div#cgit div.footer {
+	margin-top: 0.5em;
+	text-align: center;
+	font-size: 80%;
+	color: #ccc;
+}
+
+div#cgit div.footer a {
+	color: #ccc;
+	text-decoration: none;
+}
+
+div#cgit div.footer a:hover {
+	text-decoration: underline;
+}
+
+div#cgit a.branch-deco {
+	color: #000;
+	margin: 0px 0.5em;
+	padding: 0px 0.25em;
+	background-color: #88ff88;
+	border: solid 1px #007700;
+}
+
+div#cgit a.tag-deco {
+	color: #000;
+	margin: 0px 0.5em;
+	padding: 0px 0.25em;
+	background-color: #ffff88;
+	border: solid 1px #777700;
+}
+
+div#cgit a.tag-annotated-deco {
+	color: #000;
+	margin: 0px 0.5em;
+	padding: 0px 0.25em;
+	background-color: #ffcc88;
+	border: solid 1px #777700;
+}
+
+div#cgit a.remote-deco {
+	color: #000;
+	margin: 0px 0.5em;
+	padding: 0px 0.25em;
+	background-color: #ccccff;
+	border: solid 1px #000077;
+}
+
+div#cgit a.deco {
+	color: #000;
+	margin: 0px 0.5em;
+	padding: 0px 0.25em;
+	background-color: #ff8888;
+	border: solid 1px #770000;
+}
+
+div#cgit div.commit-subject a.branch-deco,
+div#cgit div.commit-subject a.tag-deco,
+div#cgit div.commit-subject a.tag-annotated-deco,
+div#cgit div.commit-subject a.remote-deco,
+div#cgit div.commit-subject a.deco {
+	margin-left: 1em;
+	font-size: 75%;
+}
+
+div#cgit table.stats {
+	border: solid 1px black;
+	border-collapse: collapse;
+}
+
+div#cgit table.stats th {
+	text-align: left;
+	padding: 1px 0.5em;
+	background-color: #eee;
+	border: solid 1px black;
+}
+
+div#cgit table.stats td {
+	text-align: right;
+	padding: 1px 0.5em;
+	border: solid 1px black;
+}
+
+div#cgit table.stats td.total {
+	font-weight: bold;
+	text-align: left;
+}
+
+div#cgit table.stats td.sum {
+	color: #c00;
+	font-weight: bold;
+/*	background-color: #eee; */
+}
+
+div#cgit table.stats td.left {
+	text-align: left;
+}
+
+div#cgit table.vgraph {
+	border-collapse: separate;
+	border: solid 1px black;
+	height: 200px;
+}
+
+div#cgit table.vgraph th {
+	background-color: #eee;
+	font-weight: bold;
+	border: solid 1px white;
+	padding: 1px 0.5em;
+}
+
+div#cgit table.vgraph td {
+	vertical-align: bottom;
+	padding: 0px 10px;
+}
+
+div#cgit table.vgraph div.bar {
+	background-color: #eee;
+}
+
+div#cgit table.hgraph {
+	border: solid 1px black;
+	width: 800px;
+}
+
+div#cgit table.hgraph th {
+	background-color: #eee;
+	font-weight: bold;
+	border: solid 1px black;
+	padding: 1px 0.5em;
+}
+
+div#cgit table.hgraph td {
+	vertical-align: middle;
+	padding: 2px 2px;
+}
+
+div#cgit table.hgraph div.bar {
+	background-color: #eee;
+	height: 1em;
+}
+
+div#cgit table.ssdiff {
+	width: 100%;
+}
+
+div#cgit table.ssdiff td {
+	font-size: 75%;
+	font-family: monospace;
+	white-space: pre;
+	padding: 1px 4px 1px 4px;
+	border-left: solid 1px #aaa;
+	border-right: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.add {
+	color: black;
+	background: #cfc;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff td.add_dark {
+	color: black;
+	background: #aca;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff span.add {
+	background: #cfc;
+	font-weight: bold;
+}
+
+div#cgit table.ssdiff td.del {
+	color: black;
+	background: #fcc;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff td.del_dark {
+	color: black;
+	background: #caa;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff span.del {
+	background: #fcc;
+	font-weight: bold;
+}
+
+div#cgit table.ssdiff td.changed {
+	color: black;
+	background: #ffc;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff td.changed_dark {
+	color: black;
+	background: #cca;
+	min-width: 50%;
+}
+
+div#cgit table.ssdiff td.lineno {
+	color: black;
+	background: #eee;
+	text-align: right;
+	width: 3em;
+	min-width: 3em;
+}
+
+div#cgit table.ssdiff td.hunk {
+	color: black;
+	background: #ccf;
+	border-top: solid 1px #aaa;
+	border-bottom: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.head {
+	border-top: solid 1px #aaa;
+	border-bottom: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.head div.head {
+	font-weight: bold;
+	color: black;
+}
+
+div#cgit table.ssdiff td.foot {
+	border-top: solid 1px #aaa;
+	border-left: none;
+	border-right: none;
+	border-bottom: none;
+}
+
+div#cgit table.ssdiff td.space {
+	border: none;
+}
+
+div#cgit table.ssdiff td.space div {
+	min-height: 3em;
+}
+* { line-height: 1.25em; }
+
+article {
+  font-family: sans-serif;
+  max-width: 70ch;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+div#cgit {
+  margin: auto;
+  font-family: monospace;
+  -moz-tab-size: 4;
+  tab-size: 4;
+  display: table;
+}
+
+div#cgit table#header {
+  margin-left: auto;
+  margin-right: auto;
+}
+div#cgit table#header td.logo {
+  display: none;
+}
+div#cgit table#header td.main {
+  font-size: 2em;
+  font-weight: bold;
+}
+div#cgit table#header td.sub {
+  border-top: none;
+}
+div#cgit table.tabs {
+  margin-left: auto;
+  margin-right: auto;
+  border-bottom: none;
+}
+div#cgit div.content {
+  border-bottom: none;
+  min-width: 108ch;
+}
+div#cgit div.content div#summary {
+  display: table;
+  margin-left: auto;
+  margin-right: auto;
+}
+div#cgit table.list {
+  margin-left: auto;
+  margin-right: auto;
+}
+div#cgit table.list th a {
+  color: inherit;
+}
+div#cgit table.list tr:nth-child(even) {
+  background: inherit;
+}
+div#cgit table.list tr:hover {
+  background: inherit;
+}
+div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+  background: inherit;
+}
+div#cgit table.list td:last-child {
+  width: 0;
+}
+div#cgit div.footer {
+  font-size: 1em;
+  margin-top: 0;
+}
+
+div#cgit table.blob td.linenumbers:nth-last-child(3) {
+  display: none;
+}
+
+div#cgit table.blob td.linenumbers a:target {
+  color: goldenrod;
+  text-decoration: underline;
+  outline: none;
+}
diff --git a/config-files/cgit/cgitrc b/config-files/cgit/cgitrc
@@ -0,0 +1,42 @@
+css=/cgit-ctucx.css
+logo=/cgit.png
+virtual-root=/
+
+root-title=ctucx.cgit
+root-desc=
+
+local-time=1
+
+readme=:README.md
+about-filter=${pkgs.cgit}/lib/cgit/filters/about-formatting.sh
+
+snapshots=tar.gz tar.bz2 zip
+
+max-stats=quarter
+
+clone-url=http://cgit.ctu.cx/$CGIT_REPO_URL git@wanderduene.ctucx.network:$CGIT_REPO_URL
+
+enable-commit-graph=1
+
+enable-index-links=1
+enable-index-owner=0
+
+enable-blame=1
+
+enable-log-filecount=1
+enable-log-linecount=1
+
+enable-http-clone=1
+enable-git-config=1
+
+mimetype.gif=image/gif
+mimetype.html=text/html
+mimetype.jpg=image/jpeg
+mimetype.jpeg=image/jpeg
+mimetype.pdf=application/pdf
+mimetype.png=image/png
+mimetype.svg=image/svg+xml
+
+remove-suffix=1
+project-list=/var/lib/git/projects.list
+scan-path=/var/lib/git/repositories
diff --git a/config-files/gitolite/gitolite.rc.patch b/config-files/gitolite/gitolite.rc.patch
@@ -0,0 +1,11 @@
+--- .gitolite.rc.default
++++ .gitolite.rc
+@@ -18,7 +18,7 @@
+
+     # default umask gives you perms of '0700'; see the rc file docs for
+     # how/why you might change this
+-    UMASK                           =>  0077,
++    UMASK                           =>  0027,
+
+     # look for "git-config" in the documentation
+     GIT_CONFIG_KEYS => "gitolite\.mirror\..*",
diff --git a/config-files/nginx/nginx.conf b/config-files/nginx/nginx.conf
@@ -0,0 +1,52 @@
+user nginx;
+
+worker_processes auto;
+
+pcre_jit on;
+
+error_log /var/log/nginx/error.log warn;
+
+include /etc/nginx/modules/*.conf;
+
+
+events {
+	worker_connections 1024;
+}
+
+http {
+	include /etc/nginx/mime.types;
+	default_type application/octet-stream;
+
+	server_tokens off;
+
+	server_names_hash_bucket_size 64;
+
+	client_max_body_size 1m;
+
+	keepalive_timeout 65;
+
+	sendfile on;
+
+	tcp_nodelay on;
+
+	ssl_prefer_server_ciphers on;
+
+	ssl_session_cache shared:SSL:2m;
+
+
+	gzip on;
+
+	gzip_vary on;
+
+	#gzip_static on;
+
+
+	# Specifies the main log format.
+	log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+			'$status $body_bytes_sent "$http_referer" '
+			'"$http_user_agent" "$http_x_forwarded_for"';
+
+	access_log /var/log/nginx/access.log main;
+
+	include /etc/nginx/conf.d/*.conf;
+}
diff --git a/config-files/nginx/ssl.conf b/config-files/nginx/ssl.conf
@@ -0,0 +1,21 @@
+ssl_session_timeout 1d;
+ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
+ssl_session_tickets off;
+
+# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
+ssl_dhparam /etc/nginx/dhparam;
+
+# intermediate configuration
+ssl_protocols TLSv1.2 TLSv1.3;
+ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
+ssl_prefer_server_ciphers off;
+
+# HSTS (ngx_http_headers_module is required) (63072000 seconds)
+add_header Strict-Transport-Security "max-age=63072000" always;
+
+# OCSP stapling
+ssl_stapling on;
+ssl_stapling_verify on;
+
+# replace with the IP address of your resolver
+resolver 127.0.0.1;
diff --git a/config-files/pleroma/config.exs b/config-files/pleroma/config.exs
@@ -0,0 +1,104 @@
+import Config
+
+config :pleroma, Pleroma.Web.Endpoint,
+  url: [host: "pleroma.ctu.cx", scheme: "https", port: 443],
+  domain: "ctu.cx",
+  http: [ip: {127, 0, 0, 1}, port: 4000]
+
+config :pleroma, Pleroma.Repo,
+  adapter:    Ecto.Adapters.Postgres,
+  username:   "pleroma",
+  database:   "pleroma",
+  socket_dir: "/run/postgresql",
+  pool_size: 10
+
+
+# We can't store the secrets in this file, since this is baked into the docker image
+if not File.exists?("/var/lib/pleroma/secret.exs") do
+  secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
+  signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
+  {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
+
+  secret_file =
+    EEx.eval_string(
+      """
+      import Config
+
+      config :pleroma, Pleroma.Web.Endpoint,
+        secret_key_base: "<%= secret %>",
+        signing_salt: "<%= signing_salt %>"
+
+      config :web_push_encryption, :vapid_details,
+        public_key: "<%= web_push_public_key %>",
+        private_key: "<%= web_push_private_key %>"
+      """,
+      secret: secret,
+      signing_salt: signing_salt,
+      web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
+      web_push_private_key: Base.url_encode64(web_push_private_key, padding: false)
+    )
+
+  File.write("/var/lib/pleroma/secret.exs", secret_file)
+end
+
+# Configure web push notifications
+config :web_push_encryption, :vapid_details, subject: "mailto:pleroma@ctu.cx"
+
+config :pleroma, :database, rum_enabled: false
+config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
+config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
+
+config :pleroma, :static_fe, enabled: false
+
+config :pleroma, :frontend_configurations,
+  pleroma_fe: %{
+    theme: "breezy-dark",
+    background: "/static/bg.png",
+    logo: "/static/logo.png",
+    chatDisabled: true,
+    webPushNotifications: true,
+    showFeaturesPanel: false,
+    collapseMessageWithSubject: false,
+    hideUserStats: false
+  }
+
+config :pleroma, :instance,
+  name: "ctucx.pleroma",
+  email: "pleroma@ctu.cx",
+  limit: 5000,
+  registrations_open: false,
+  invites_enabled: true,
+  account_activation_required: false,
+  remote_post_retention_days: 50,
+  external_user_synchronization: true,
+  allowed_post_formats: [
+    "text/plain",
+    "text/html",
+    "text/markdown"
+  ]
+
+config :pleroma, :media_proxy,
+  enabled: false,
+  redirect_on_failure: true,
+  base_url: "https://cache.domain.tld"
+
+config :pleroma, :fetch_initial_posts,
+  enabled: false,
+  pages: 1
+
+config :pleroma, :chat, enabled: false
+
+config :pleroma, :emoji,
+  shortcode_globs: ["/emoji/custom/**/*.png"],
+  groups: [
+    "Bahn":           "/emoji/cuties/Bahn/*.png",
+    "Blobs":          "/emoji/cuties/Blobs/*.png",
+    "Bread":          "/emoji/cuties/Bread/*.png",
+    "LGBTIQ*":        "/emoji/cuties/LGBTIQ\*/*.png",
+    "Signale":        "/emoji/cuties/Signale/*.png",
+    "naughty_goose":  "/emoji/cuties/naughty_goose/*.png",
+    'Technology':     "/emoji/cuties/Technology/*.png",
+    "Transportation": "/emoji/cuties/Transportation/*.png",
+    "Chaos":          "/emoji/chaos/*.png",
+    "femojis":        "/emoji/femojis/*.png"
+  ]
diff --git a/config-files/prometheus/prometheus.yml b/config-files/prometheus/prometheus.yml
@@ -0,0 +1,39 @@
+global:
+  scrape_interval:     20s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
+  evaluation_interval: 1m # Evaluate rules every 15 seconds. The default is every 1 minute.
+
+alerting:
+  alertmanagers:
+  - static_configs:
+    - targets:
+      # - alertmanager:9093
+
+
+rule_files:
+  # - "first_rules.yml"
+  # - "second_rules.yml"
+
+scrape_configs:
+  - job_name: 'prometheus'
+    static_configs:
+    - targets: ['localhost:9090']
+
+  - job_name: 'node-exporter'
+    metrics_path: '/node-exporter'
+    scheme: 'https'
+    scrape_interval: 30s
+    static_configs:
+    - targets: [
+      'wanderduene.ctu.cx',
+      'taurus.ctu.cx'
+    ]
+
+  - job_name: 'fritzbox-exporter'
+    metrics_path: '/metrics'
+    scheme: 'https'
+    scrape_interval: 30s
+    static_configs:
+    - targets: [
+      'fbexporter.ctu.cx',
+      'fbexporter.f2k1.de'
+    ]
diff --git a/config-files/radicale/config b/config-files/radicale/config
@@ -0,0 +1,48 @@
+# Config file for Radicale - A simple calendar server
+
+[server]
+hosts = localhost:5232
+#max_connections = 8
+#max_content_length = 100000000
+#timeout = 30
+#ssl = False
+#certificate = /etc/ssl/radicale.cert.pem
+#key = /etc/ssl/radicale.key.pem
+#certificate_authority =
+
+[encoding]
+request = utf-8
+stock = utf-8
+
+
+[auth]
+type = htpasswd
+htpasswd_filename = /etc/radicale/users
+htpasswd_encryption = plain
+#delay = 1
+#realm = Radicale - Password Required
+
+
+[rights]
+#type = owner_only
+#file = /etc/radicale/rights
+
+
+[storage]
+#type = multifilesystem
+#filesystem_folder = /var/lib/radicale/collections
+#max_sync_token_age = 2592000
+#hook =
+
+
+[web]
+type = internal
+
+
+[logging]
+#level = warning
+#mask_passwords = True
+
+
+[headers]
+Access-Control-Allow-Origin = *
diff --git a/config-files/riot-web/config.json b/config-files/riot-web/config.json
@@ -0,0 +1,55 @@
+{
+    "default_server_config": {
+        "m.homeserver": {
+            "base_url": "https://matrix.ctu.cx",
+            "server_name": "ctu.cx"
+        },
+        "m.identity_server": {
+            "base_url": "https://vector.im"
+        }
+    },
+    "disable_custom_urls": false,
+    "disable_guests": false,
+    "disable_login_language_selector": false,
+    "disable_3pid_login": true,
+    "brand": "ctucx.matrix",
+    "integrations_ui_url": "https://scalar.vector.im/",
+    "integrations_rest_url": "https://scalar.vector.im/api",
+    "integrations_widgets_urls": [
+        "https://scalar.vector.im/_matrix/integrations/v1",
+        "https://scalar.vector.im/api",
+        "https://scalar-staging.vector.im/_matrix/integrations/v1",
+        "https://scalar-staging.vector.im/api",
+        "https://scalar-staging.riot.im/scalar/api"
+    ],
+    "bug_report_endpoint_url": "https://element.io/bugreports/submit",
+    "defaultCountryCode": "DE",
+    "showLabsSettings": true,
+    "features": {
+        "feature_new_spinner": true
+    },
+    "default_federate": true,
+    "default_theme": "dark",
+    "roomDirectory": {
+        "servers": [
+            "matrix.org"
+        ]
+    },
+    "welcomeUserId": "@riot-bot:matrix.org",
+    "piwik": {
+        "url": "https://piwik.riot.im/",
+        "whitelistedHSUrls": ["https://matrix.org"],
+        "whitelistedISUrls": ["https://vector.im", "https://matrix.org"],
+        "siteId": 1
+    },
+    "enable_presence_by_hs_url": {
+        "https://matrix.org": false,
+        "https://matrix-client.matrix.org": false
+    },
+    "settingDefaults": {
+        "breadcrumbs": true
+    },
+    "jitsi": {
+        "preferredDomain": "jitsi.riot.im"
+    }
+}
diff --git a/config-files/ssh/sshd_config.patch b/config-files/ssh/sshd_config.patch
@@ -0,0 +1,29 @@
+--- sshd_config
++++ /etc/ssh/sshd_config
+@@ -29,7 +29,7 @@
+ # Authentication:
+
+ #LoginGraceTime 2m
+-PermitRootLogin yes
++PermitRootLogin prohibit-password
+ #StrictModes yes
+ #MaxAuthTries 6
+ #MaxSessions 10
+@@ -54,7 +54,7 @@
+ #IgnoreRhosts yes
+
+ # To disable tunneled clear text passwords, change to no here!
+-#PasswordAuthentication yes
++PasswordAuthentication no
+ #PermitEmptyPasswords no
+
+ # Change to no to disable s/key passwords
+@@ -83,7 +83,7 @@
+
+ #AllowAgentForwarding yes
+ # Feel free to re-enable these if your use case requires them.
+-AllowTcpForwarding no
++AllowTcpForwarding yes
+ GatewayPorts no
+ X11Forwarding no
+ #X11DisplayOffset 10
diff --git a/config-files/sudo/sudoers.patch b/config-files/sudo/sudoers.patch
@@ -0,0 +1,11 @@
+--- sudoers
++++ /etc/sudoers
+@@ -79,7 +79,7 @@
+ root ALL=(ALL) ALL
+
+ ## Uncomment to allow members of group wheel to execute any command
+-# %wheel ALL=(ALL) ALL
++%wheel ALL=(ALL) ALL
+
+ ## Same thing without a password
+ # %wheel ALL=(ALL) NOPASSWD: ALL
diff --git a/config-files/synapse/homeserver.yaml b/config-files/synapse/homeserver.yaml
@@ -0,0 +1,88 @@
+no_tls: false
+
+server_name: "ctu.cx"
+pid_file: "/run/matrix-synapse.pid"
+
+public_baseurl: "https://matrix.ctu.cx/"
+
+listeners:
+  - port: 8008
+    bind_address: "0.0.0.0"
+    type: http
+    tls: false
+    x_forwarded: true
+    resources:
+      - names:
+          - client
+        compress: true
+      - names:
+          - federation
+        compress: false
+
+database:
+  name: "psycopg2"
+  args:
+    database: "synapse"
+
+
+event_cache_size: "10K"
+verbose: 0
+log_config: "/etc/synapse/log.yaml"
+
+rc_messages_per_second: 0.2
+rc_message_burst_count: 10.0
+
+federation_rc_window_size: 1000
+federation_rc_sleep_limit: 10
+federation_rc_sleep_delay: 500
+federation_rc_reject_limit: 50
+federation_rc_concurrent: 3
+
+media_store_path: "/var/lib/synapse/media"
+uploads_path: "/var/lib/synapse/uploads"
+max_upload_size: "100M"
+max_image_pixels: "32M"
+dynamic_thumbnails: false
+
+url_preview_enabled: true
+url_preview_ip_range_blacklist: ["127.0.0.0/8","10.0.0.0/8","172.16.0.0/12","192.168.0.0/16","100.64.0.0/10","169.254.0.0/16","::1/128","fe80::/64","fc00::/7"]
+url_preview_ip_range_whitelist: []
+url_preview_url_blacklist: []
+
+recaptcha_private_key: ""
+recaptcha_public_key: ""
+enable_registration_captcha: false
+
+turn_uris: []
+turn_shared_secret: ""
+enable_registration: false
+enable_metrics: false
+registration_shared_secret: "secret"
+
+recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
+turn_user_lifetime: "1h"
+user_creation_max_duration: 1209600000
+bcrypt_rounds: 12
+allow_guest_access: false
+
+account_threepid_delegates:
+
+room_invite_state_types:
+  - "m.room.join_rules"
+  - "m.room.canonical_alias"
+  - "m.room.avatar"
+  - "m.room.name"
+
+expire_access_token: false
+report_stats: false
+signing_key_path: "/var/lib/synapse/homeserver.signing.key"
+key_refresh_interval: "1d"
+
+redaction_retention_period: 7
+
+perspectives:
+  servers:
+    "matrix.org":
+      verify_keys:
+        "ed25519:auto":
+          key: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"
diff --git a/config-files/synapse/log.yaml b/config-files/synapse/log.yaml
@@ -0,0 +1,39 @@
+# Log configuration for Synapse.
+version: 1
+
+formatters:
+    precise:
+        format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
+
+handlers:
+    file:
+        class: logging.handlers.TimedRotatingFileHandler
+        formatter: precise
+        filename: /var/log/synapse/homeserver.log
+        when: midnight
+        backupCount: 3  # Does not include the current log file.
+        encoding: utf8
+
+    buffer:
+        class: logging.handlers.MemoryHandler
+        target: file
+        capacity: 10
+        flushLevel: 30  # Flush for WARNING logs as well
+
+    console:
+        class: logging.StreamHandler
+        formatter: precise
+
+loggers:
+    synapse.storage.SQL:
+        level: INFO
+
+    twisted:
+        handlers: [file]
+        propagate: false
+
+root:
+    level: INFO
+    handlers: [buffer]
+
+disable_existing_loggers: false
diff --git a/config-files/syncthing/syncthing.initd b/config-files/syncthing/syncthing.initd
@@ -0,0 +1,20 @@
+#!/sbin/openrc-run
+
+name=$RC_SVCNAME
+command=/usr/bin/syncthing
+command_args="${SYNCTHING_ARGS:--no-browser}"
+command_user="leah:leah"
+pidfile=/run/${RC_SVCNAME}.pid
+command_background=yes
+start_stop_daemon_args="--stdout /var/log/$RC_SVCNAME/${RC_SVCNAME}.log --stderr /var/log/$RC_SVCNAME/${RC_SVCNAME}.log"
+
+depend() {
+        use logger dns
+        need net
+        after firewall
+}
+
+start_pre() {
+        checkpath --directory --owner $command_user --mode 0775 \
+                /var/log/$RC_SVCNAME
+}
diff --git a/config-files/website-vhosts/ctu.cx.conf b/config-files/website-vhosts/ctu.cx.conf
@@ -0,0 +1,26 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "/var/lib/acme-redirect/live/ctu.cx/fullchain";
+	ssl_certificate_key "/var/lib/acme-redirect/live/ctu.cx/privkey";
+	include /etc/nginx/ssl.conf;
+	
+	server_name ctu.cx;
+
+	root /var/lib/websites/ctu.cx;
+
+	location /.well-known/host-meta {
+		return 301 https://pleroma.ctu.cx$request_uri;
+	}
+
+	location /.well-known/matrix/client {
+		return 200 '{"m.homeserver": {"base_url": "https://matrix.ctu.cx"}}';
+		add_header Content-Type application/json;
+	}
+
+	location /.well-known/matrix/server {
+		return 200 '{"m.server": "matrix.ctu.cx:443"}';
+		add_header Content-Type application/json;
+	}
+}
diff --git a/config-files/website-vhosts/photos.ctu.cx.conf b/config-files/website-vhosts/photos.ctu.cx.conf
@@ -0,0 +1,20 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "/var/lib/acme-redirect/live/photos.ctu.cx/fullchain";
+	ssl_certificate_key "/var/lib/acme-redirect/live/photos.ctu.cx/privkey";
+	include /etc/nginx/ssl.conf;
+	
+	server_name photos.ctu.cx;
+
+	root /var/lib/websites/photos.ctu.cx;
+
+	location ~* \.(html)$ {
+		add_header Last-Modified $date_gmt;
+		add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
+		if_modified_since off;
+		expires off;
+		etag off;
+	}
+}
diff --git a/inventory b/inventory
@@ -0,0 +1,9 @@
+[all:vars]
+ansible_ssh_user=root
+
+[taurus]
+taurus.ctu.cx
+
+
+[wanderduene]
+wanderduene.ctu.cx
diff --git a/playbooks.yml b/playbooks.yml
@@ -0,0 +1,201 @@
+---
+- hosts: all
+  remote_user: root
+  gather_facts: false
+  tasks:
+    - name: Install Python
+      raw: test -e /usr/bin/python || (apk update && apk add python3)
+
+
+
+- hosts: taurus
+  name: Install taurus
+  roles:
+    - common
+#    - bind
+#    - acme-redirect
+#    - nginx
+#    - syncthing
+#    - websites
+  vars:
+    network:
+      interface: eth0
+      hostname: taurus
+      domain: ctu.cx
+      nameservers:
+        - 1.1.1.1
+        - 8.8.8.8
+      ipv4:
+        address: 37.221.196.131
+        gateway: 37.221.196.1
+        netmask: 255.255.255.0
+      ipv6:
+        address: 2a03:4000:9:f8::1
+        gateway: fe80::1
+        netmask: 64
+    bind:
+      type: slave
+      masters:
+        - 46.38.253.139
+      domains:
+        - ctu.cx
+        - ctucx.de
+        - ctucx.network
+        - thein.ovh
+        - antifa.jetzt
+        - antifa.life
+        - antifa.email
+        - oeffisear.ch
+    nginx:
+      ssl_cert: "/var/lib/acme-redirect/live/taurus.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/taurus.ctu.cx/privkey"
+    acme_redirect_certs:
+      taurus.ctu.cx:
+        dns_names: 
+          - taurus.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/taurus.ctu.cx
+          - sudo rc-service nginx restart
+      syncthing.ctu.cx:
+        dns_names: 
+          - syncthing.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/syncthing.ctu.cx
+          - sudo rc-service nginx restart
+      photos.ctu.cx:
+        dns_names: 
+          - photos.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/photo.ctu.cx
+          - sudo rc-service nginx restart
+    syncthing:
+      domain: "syncthing.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/syncthing.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/syncthing.ctu.cx/privkey"
+
+
+
+- hosts: wanderduene
+  name:  Install wanderduene
+  roles: 
+    - common
+#    - bind
+#    - acme-redirect
+#    - nginx
+#    - gitolite
+#    - cgit
+#    - oeffisearch
+#    - maddy
+#    - prometheus
+#    - radicale
+#    - websites
+#    - pleroma
+#    - synapse
+  vars:
+    network:
+      interface: eth0
+      hostname: wanderduene
+      domain: ctu.cx
+      nameservers:
+        - 1.1.1.1
+        - 8.8.8.8
+      ipv4:
+        address: 46.38.253.139
+        gateway: 46.38.253.1
+        netmask: 255.255.255.0
+      ipv6:
+        address: 2a03:4000:1:45d::1
+        gateway: fe80::1
+        netmask: 64
+    bind:
+      type: master
+      slaves:
+        - 37.221.196.131
+        - 195.39.247.15
+      domains:
+        - ctu.cx
+        - ctucx.de
+        - ctucx.network
+        - thein.ovh
+        - antifa.jetzt
+        - antifa.life
+        - antifa.email
+        - oeffisear.ch
+    acme_redirect_certs:
+      wanderduene.ctu.cx:
+        dns_names: 
+          - wanderduene.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/wanderduene.ctu.cx
+          - sudo rc-service nginx restart
+          - sudo rc-service maddy restart
+      metrics.wanderduene.ctu.cx:
+        dns_names: 
+          - metrics.wanderduene.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/metrics.wanderduene.ctu.cx
+          - sudo rc-service nginx restart
+      ctucx.de:
+        dns_names:
+          - ctucx.de
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/ctucx.de
+          - sudo rc-service nginx restart
+      ctu.cx:
+        dns_names:
+          - ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/ctu.cx
+          - sudo rc-service nginx restart
+      matrix.ctu.cx:
+        dns_names:
+          - matrix.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/matrix.ctu.cx
+          - sudo rc-service nginx restart
+      dav.ctu.cx:
+        dns_names: 
+          - dav.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/dav.ctu.cx
+          - sudo rc-service nginx restart
+      cgit.ctu.cx:
+        dns_names:
+          - cgit.ctu.cx
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/cgit.ctu.cx
+          - sudo rc-service nginx restart
+      oeffisear.ch:
+        dns_names:
+          - oeffisear.ch
+        renew_tasks:
+          - chown -R acme-redirect:acme-redirect /var/lib/acme-redirect/live/oeffisear.ch
+          - sudo rc-service nginx restart
+    nginx:
+      ssl_cert: "/var/lib/acme-redirect/live/wanderduene.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/wanderduene.ctu.cx/privkey"
+    cgit:
+      domain: "cgit.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/cgit.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/cgit.ctu.cx/privkey"
+    oeffisearch:
+      domain: "oeffisear.ch"
+      ssl_cert: "/var/lib/acme-redirect/live/oeffisear.ch/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/oeffisear.ch/privkey"
+    maddy:
+      hostname: "wanderduene.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/wanderduene.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/wanderduene.ctu.cx/privkey"
+    prometheus:
+      domain: "metrics.wanderduene.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/metrics.wanderduene.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/metrics.wanderduene.ctu.cx/privkey"
+    radicale:
+      domain: "dav.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/dav.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/dav.ctu.cx/privkey"
+    synapse:
+      domain: "matrix.ctu.cx"
+      ssl_cert: "/var/lib/acme-redirect/live/matrix.ctu.cx/fullchain"
+      ssl_privkey: "/var/lib/acme-redirect/live/matrix.ctu.cx/privkey"
+    gitolite_initialKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw/G6x8H3ojvHx3NsTswBMMmOhp48F3rea0GUniKSvRLMRIti5b7Q4P4FXnkQEtuNSR3u7gE5r4EacaLaIx7Az9SgHRoE+hdzSo4mPAwKTx/E3HZgIjdZhTDL8PAn4SZZT6RBqr/uGb+x9fdIjY0FbdNBLjq0MNnG3T+qd1joUL8JXoS7F//ac52RhHlsA5qJXFDOhpqR/7hRMwOFNH0GKaLN1xQKcOjhpIcdswpOf8kRDVpT7xOYwfXCFF4MaY2M8047WKarvEnGdADIIw6bvWsdJINehtOQmYEFRaMuaWp1d9bglZXZKPQKNubv5lqneMP4AI7ImDYjgW6eNLIT1 cardno:000603502829"
diff --git a/roles/acme-redirect/tasks/main.yml b/roles/acme-redirect/tasks/main.yml
@@ -0,0 +1,56 @@
+---
+
+- name: Install acme-redirect
+  apk:
+   name: acme-redirect
+   state: present
+   update_cache: yes
+
+- name: create sudoers file for acme-redirect
+  copy:
+    content: "acme-redirect ALL=NOPASSWD:/sbin/rc-service\n"
+    dest: /etc/sudoers.d/acme-redirect
+
+- name: copy acme-redirect config to destination host
+  copy:
+    src: config-files/acme-redirect/acme-redirect.conf
+    dest: /etc/acme-redirect.conf
+    owner: acme-redirect
+    group: acme-redirect
+
+- name: clean cert-config directory
+  file:
+    state: "{{ item }}"
+    path: /etc/acme-redirect.d
+    owner: acme-redirect
+    group: acme-redirect
+    mode: 0755
+  with_items:
+    - absent
+    - directory
+
+- name: create configs for defined certs
+  template:
+    src: acme-redirect.conf.j2
+    dest: /etc/acme-redirect.d/{{item.key}}.conf
+    owner: acme-redirect
+    group: acme-redirect
+    mode: 0644
+  loop: "{{ lookup('dict', acme_redirect_certs) }}"
+
+- name: Copy http(s) firewall-rule to destination host
+  copy:
+    src: config-files/awall/web.json
+    dest: /etc/awall/optional/web.json
+    validate: jq '.' %s
+
+- awall:
+   name: web
+   state: enabled
+   activate: yes
+
+- name: Enable and start acme-redirect
+  service:
+   name: acme-redirect
+   enabled: yes
+   state: restarted
diff --git a/roles/acme-redirect/templates/acme-redirect.conf.j2 b/roles/acme-redirect/templates/acme-redirect.conf.j2
@@ -0,0 +1,12 @@
+[cert]
+name      = "{{item.key}}"
+dns_names = [
+{% for domain in item.value.dns_names %}
+    "{{domain}}",
+{% endfor %}
+]
+exec = [
+{% for task in item.value.renew_tasks %}
+    "{{task}}",
+{% endfor %}
+]
diff --git a/roles/bind/tasks/main.yml b/roles/bind/tasks/main.yml
@@ -0,0 +1,48 @@
+---
+
+- name: Install bind dns-server
+  apk:
+   name: bind
+   state: present
+   update_cache: yes
+
+- name: clone the dns-zones
+  git:
+    repo: 'https://cgit.ctu.cx/dns-zones'
+    dest: /var/lib/named/zones
+  when: bind.type == "master"
+
+
+- name: change ownership 
+  file:
+    path: /var/lib/named
+    owner: named
+    group: named
+    state: directory
+    recurse: yes
+  when: bind.type == "master"
+
+- name: copy named.conf to destination host
+  template:
+    src: named.conf.j2
+    dest: /etc/bind/named.conf
+    owner:  named
+    group: named
+
+- name: Enable and start bind dns-server
+  service:
+    name: named
+    enabled: yes
+    state: restarted
+
+- name: Copy dns firewall-rule to destination host
+  copy:
+    src: config-files/awall/dns.json
+    dest: /etc/awall/optional/dns.json
+    validate: jq '.' %s
+
+- name: activate new firewall-rules
+  awall:
+    name: dns
+    state: enabled
+    activate: yes
diff --git a/roles/bind/templates/named.conf.j2 b/roles/bind/templates/named.conf.j2
@@ -0,0 +1,32 @@
+options { 
+	directory "/var/lib/named"; 
+	notify yes;
+{% if bind.type == "master" %}
+	allow-transfer {
+{% for slave in bind.slaves %}
+		{{ slave }};
+{% endfor %}
+	};
+{% endif %}
+};
+
+
+{% for domain in bind.domains %}
+zone "{{ domain }}" in {
+	type {{ bind.type }};
+{% if bind.type == "master" %}
+	file "/var/lib/named/zones/{{ domain }}.zone";
+{% else %}
+	file "/var/lib/named/{{ domain }}.zone";
+{% endif %}
+
+{% if bind.type == "slave" %}
+	masters {
+{% for master in bind.masters %}
+		{{ master }};
+{% endfor %}
+	};
+{% endif %}
+};
+
+{% endfor %}
diff --git a/roles/cgit/tasks/main.yml b/roles/cgit/tasks/main.yml
@@ -0,0 +1,53 @@
+---
+
+- name: Install cgit
+  apk:
+   name: cgit git  spawn-fcgi fcgiwrap
+   state: present
+   update_cache: yes
+
+- name: create fcgi-service
+  file:
+    src: /etc/init.d/spawn-fcgi
+    dest: /etc/init.d/spawn-fcgi.cgit
+    state: link
+
+- copy: 
+    content: "FCGI_PORT=8001\nFCGI_PROGRAM=/usr/bin/fcgiwrap"
+    dest: /etc/conf.d/spawn-fcgi.cgit
+
+- service:
+   name: spawn-fcgi.cgit
+   enabled: yes
+   state: restarted
+
+- name: copy nginx-vhost for cgit to destination host 
+  template: 
+    src: cgit-vhost.conf.j2
+    dest: /etc/nginx/conf.d/cgit.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- name: copy cgit-config to destination host 
+  copy: 
+    src: config-files/cgit/cgitrc
+    dest: /etc/cgitrc
+    mode: 0644
+
+- name: copy cgit.css to destination host 
+  copy: 
+    src: config-files/cgit/cgit.css
+    dest: /usr/share/webapps/cgit/cgit-ctucx.css
+    mode: 0644
+
+- name: adding user nginx to group git
+  user:
+    name: nginx
+    groups: git
+    append: yes
+
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted
diff --git a/roles/cgit/templates/cgit-vhost.conf.j2 b/roles/cgit/templates/cgit-vhost.conf.j2
@@ -0,0 +1,21 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{cgit.ssl_cert}}";
+	ssl_certificate_key "{{cgit.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{cgit.domain}};
+
+	root /usr/share/webapps/cgit;
+	try_files $uri @cgit;
+
+	location @cgit {
+		include fastcgi_params;
+		fastcgi_pass localhost:8001;
+		fastcgi_param SCRIPT_FILENAME /usr/share/webapps/cgit/cgit.cgi;
+		fastcgi_param PATH_INFO $uri;
+		fastcgi_param QUERY_STRING $args;
+	}
+}
diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: run ferm
+  command: ferm /etc/ferm/ferm.conf
diff --git a/roles/common/tasks/firewall.yml b/roles/common/tasks/firewall.yml
@@ -0,0 +1,40 @@
+---
+- name: install awall
+  apk:
+    name: awall ip6tables
+
+- name: Load iptables kernel module
+  raw: "modprobe ip_tables"
+
+- name: Copy base custom-services configguration to destination host
+  copy:
+    src: config-files/awall/custom-services.json
+    dest: /etc/awall/private/custom-services.json
+    validate: jq '.' %s
+
+- name: Copy base awall(firewall) configguration to destination host
+  copy:
+    src: awall-baseconfig.json.j2
+    dest: /etc/awall/private/base.json
+    validate: jq '.' %s
+
+- name: Copy awall(firewall) configguration for ssh to destination host
+  copy:
+    src: config-files/awall/ssh.json
+    dest: /etc/awall/optional/ssh.json
+    validate: jq '.' %s
+
+- awall:
+   name: ssh
+   state: enabled
+   activate: yes
+
+- service:
+   name: iptables
+   enabled: yes
+   state: started
+
+- service:
+   name: ip6tables
+   enabled: yes
+   state: started
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+- include: packages.yml
+
+- include: network.yml
+
+- include: sudo.yml
+
+- include: sshd.yml
+
+- include: users.yml
+
+- include: firewall.yml
+
+- include: node-exporter.yml
diff --git a/roles/common/tasks/network.yml b/roles/common/tasks/network.yml
@@ -0,0 +1,30 @@
+---
+
+- name: create network-config
+  template:
+    src: interfaces.conf.j2
+    dest: /etc/network/interfaces
+    mode: 0755
+
+- name: create hosts-config
+  template:
+    src: hosts.conf.j2
+    dest: /etc/hosts
+    mode: 0755
+
+- name: create hosts-config
+  template:
+    src: resolv.conf.j2
+    dest: /etc/resolv.conf
+    mode: 0755
+
+- name: set hostname
+  copy:
+    content: "{{ network.hostname }}"
+    dest: /etc/hostname
+    mode: 0755
+
+- name: restart networking service
+  service:
+    name: networking
+    state: restarted
diff --git a/roles/common/tasks/node-exporter.yml b/roles/common/tasks/node-exporter.yml
@@ -0,0 +1,9 @@
+---
+- name: install node-exporter
+  apk:
+    name: prometheus-node-exporter
+
+- service:
+   name: node-exporter
+   enabled: yes
+   state: started
diff --git a/roles/common/tasks/packages.yml b/roles/common/tasks/packages.yml
@@ -0,0 +1,30 @@
+---
+- name: get signature from personal repo
+  get_url:
+    url: http://home.f2k1.de:8080/leah-5f817de5.rsa.pub
+    dest: /etc/apk/keys/leah-5f817de5.rsa.pub
+
+- name: switch to edge repos
+  copy:
+    content: "http://home.f2k1.de:8080/alpine-pkgs\nhttp://dl-cdn.alpinelinux.org/alpine/edge/main\nhttp://dl-cdn.alpinelinux.org/alpine/edge/community\nhttp://dl-cdn.alpinelinux.org/alpine/edge/testing"
+    dest: /etc/apk/repositories
+
+- name: update system
+  raw: "apk update && apk upgrade"
+
+- name: Install common packages
+  apk:
+    name:
+      - nano
+      - sudo
+      - htop
+      - tar
+      - unzip
+      - curl 
+      - wget
+      - tmux
+      - git
+      - patch
+      - jq
+    update_cache: yes
+    
diff --git a/roles/common/tasks/sshd.yml b/roles/common/tasks/sshd.yml
@@ -0,0 +1,12 @@
+---
+
+- name: patch sshd_config
+  patch:
+    src: config-files/ssh/sshd_config.patch
+    dest: /etc/ssh/sshd_config
+
+- name: restart sshd
+  service:
+   name: sshd
+   enabled: yes
+   state: restarted
diff --git a/roles/common/tasks/sudo.yml b/roles/common/tasks/sudo.yml
@@ -0,0 +1,12 @@
+---
+
+- name: install sudo 
+  apk:
+   name: sudo 
+   state: present
+   update_cache: yes
+
+- name: patch sudoers config
+  patch:
+    src: config-files/sudo/sudoers.patch
+    dest: /etc/sudoers
diff --git a/roles/common/tasks/users.yml b/roles/common/tasks/users.yml
@@ -0,0 +1,33 @@
+---
+
+- name: Add group for leah 
+  group:
+    name: leah
+    state: present
+    gid: 1000
+
+
+- name: Add user leah 
+  user:
+    append: yes
+    name: leah
+    uid: 1000
+    group: leah
+    groups: wheel
+    password: $6$foobar123$1qcCmnoveirSdWY9XdgH5hCXv32hj0n/AyJX46sSp1LyGCA8QT/xxifebRxr89uIH6vwhzFGgz4.H2sG0en0f0
+
+- name: create .ssh dir
+  file:
+    state: directory
+    dest: /home/leah/.ssh/
+    mode: 0755
+    owner: leah
+    group: leah
+
+- name: place ssh-key for user
+  copy:
+    content: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw/G6x8H3ojvHx3NsTswBMMmOhp48F3rea0GUniKSvRLMRIti5b7Q4P4FXnkQEtuNSR3u7gE5r4EacaLaIx7Az9SgHRoE+hdzSo4mPAwKTx/E3HZgIjdZhTDL8PAn4SZZT6RBqr/uGb+x9fdIjY0FbdNBLjq0MNnG3T+qd1joUL8JXoS7F//ac52RhHlsA5qJXFDOhpqR/7hRMwOFNH0GKaLN1xQKcOjhpIcdswpOf8kRDVpT7xOYwfXCFF4MaY2M8047WKarvEnGdADIIw6bvWsdJINehtOQmYEFRaMuaWp1d9bglZXZKPQKNubv5lqneMP4AI7ImDYjgW6eNLIT1 cardno:000603502829"
+    dest: /home/leah/.ssh/authorized_keys
+    mode: 0644    
+    owner: leah
+    group: leah
diff --git a/roles/common/templates/awall-baseconfig.json.j2 b/roles/common/templates/awall-baseconfig.json.j2
@@ -0,0 +1,28 @@
+{
+  "description": "Base zones and policies for wanderduene",
+  "import": [ "custom-services" ],
+
+  "zone": {
+    "WAN": { "iface": "{{ network.interface }}" }
+  },
+
+  "policy": [
+     { "in": "_fw", "action": "accept" },
+     { "in": "_fw", "out":  "WAN" , "action": "accept" },
+     { "in": "WAN", "action": "drop" }
+  ],
+
+  "filter": [
+    {
+      "in": "_fw",
+      "out": "WAN",
+      "service": [ "dns", "http", "https", "ssh" ]
+    },
+    {
+      "in": "WAN",
+      "out": "_fw",
+      "service": "ping",
+      "action": "accept"
+    }
+  ]
+}
diff --git a/roles/common/templates/hosts.conf.j2 b/roles/common/templates/hosts.conf.j2
@@ -0,0 +1,2 @@
+127.0.0.1	localhost localhost.localdomain {{ network.hostname }} {{ network.hostname }}.{{ network.domain }}
+::1			localhost localhost.localdomain {{ network.hostname }} {{ network.hostname }}.{{ network.domain }}
diff --git a/roles/common/templates/interfaces.conf.j2 b/roles/common/templates/interfaces.conf.j2
@@ -0,0 +1,16 @@
+auto lo
+iface lo inet loopback
+
+auto {{ network.interface }}
+iface {{ network.interface }} inet static
+	hostname {{ network.hostname }}
+	address {{ network.ipv4.address }}
+	netmask {{ network.ipv4.netmask }}
+	gateway {{ network.ipv4.gateway }}
+
+auto {{ network.interface }}
+iface {{ network.interface }} inet6 static
+	hostname {{ network.hostname }}
+	address {{ network.ipv6.address }}
+	netmask {{ network.ipv6.netmask }}
+	gateway {{ network.ipv6.gateway }}
diff --git a/roles/common/templates/resolv.conf.j2 b/roles/common/templates/resolv.conf.j2
@@ -0,0 +1,4 @@
+search {{ network.domain }}
+{% for nameserver in network.nameservers %}
+nameserver {{ nameserver }}
+{% endfor %}
diff --git a/roles/gitolite/tasks/main.yml b/roles/gitolite/tasks/main.yml
@@ -0,0 +1,58 @@
+---
+- name: Install gitolite
+  apk:
+   name: gitolite, git
+   state: present
+   update_cache: yes
+
+- fail: msg="gitolite_initialKey is not defined!"
+  when: gitolite_initialKey is not defined
+
+- name: copy initial ssh-key to destination host
+  when: gitolite_initialKey is defined
+  copy:
+    content: "{{gitolite_initialKey}}"
+    dest: /var/lib/git/first-user-key.pub
+    owner: git
+    group: git
+
+- name: Initial setup of gitolite
+  become: yes
+  become_user: git
+  command:
+    cmd: gitolite setup -pk /var/lib/git/first-user-key.pub
+    creates: /var/lib/git/.gitolite
+
+- name: Delete first-user-key.pub
+  file:
+    path: /var/lib/git/first-user-key.pub
+    state: absent
+
+- name: Unlock the git user
+  ignore_errors: yes
+  command:
+    cmd: passwd -u git
+
+- name: fix gitolite.rc to set correct permissons
+  patch:
+    src: config-files/gitolite/gitolite.rc.patch
+    dest: /var/lib/git/.gitolite.rc
+
+- name: set permissions for git dir
+  file:
+    path: /var/lib/git
+    state: directory  
+    mode: 0755
+    owner: git
+    group: git
+
+- name: Copy ssh firewall-rule to destination host
+  copy:
+    src: config-files/awall/ssh.json
+    dest: /etc/awall/optional/ssh.json
+    validate: jq '.' %s
+
+- awall:
+   name: ssh
+   state: enabled
+   activate: yes
diff --git a/roles/maddy/tasks/main.yml b/roles/maddy/tasks/main.yml
@@ -0,0 +1,37 @@
+---
+
+- name: Install maddy mailserver
+  apk:
+   name: maddy
+   state: present
+   update_cache: yes
+
+- name: adding user maddy to group acme-redirect
+  user:
+    name: maddy
+    groups: acme-redirect
+    append: yes
+
+- name: copy maddy-config to destination host 
+  template: 
+    src: maddy.conf.j2
+    dest: /etc/maddy/maddy.conf
+    mode: 0644
+    owner: maddy
+    group: maddy
+
+- name: Copy mail firewall-rule to destination host
+  copy:
+    src: config-files/awall/mail.json
+    dest: /etc/awall/optional/mail.json
+    validate: jq '.' %s
+
+- awall:
+   name: mail
+   state: enabled
+   activate: yes
+
+- service:
+   name: maddy
+   enabled: yes
+   state: restarted
diff --git a/roles/maddy/templates/maddy.conf.j2 b/roles/maddy/templates/maddy.conf.j2
@@ -0,0 +1,182 @@
+## maddy 0.4 - default configuration file
+
+# ----------------------------------------------------------------------------
+# Base variables
+ $(hostname) = {{maddy.hostname}} 
+$(primary_domain) = ctu.cx
+$(local_domains) = $(hostname) $(primary_domain) antifa.jetzt thein.ovh ctucx.de
+
+tls file {{maddy.ssl_cert}} {{maddy.ssl_privkey}}
+
+# ----------------------------------------------------------------------------
+# Local storage & authentication
+
+# pass_table provides local hashed passwords storage for authentication of
+# users. It can be configured to use any "table" module, in default
+# configuration a table in SQLite DB is used.
+# Table can be replaced to use e.g. a file for passwords. Or pass_table module
+# can be replaced altogether to use some external source of credentials (e.g.
+# PAM, /etc/shadow file).
+#
+# If table module supports it (sql_table does) - credentials can be managed
+# using 'maddyctl creds' command.
+
+auth.pass_table local_authdb {
+    table sql_table {
+        driver sqlite3
+        dsn credentials.db
+        table_name passwords
+    }
+}
+
+# imapsql module stores all indexes and metadata necessary for IMAP using a
+# relational database. It is used by IMAP endpoint for mailbox access and
+# also by SMTP & Submission endpoints for delivery of local messages.
+#
+# IMAP accounts, mailboxes and all message metadata can be inspected using
+# imap-* subcommands of maddyctl utility.
+
+storage.imapsql local_mailboxes {
+    driver sqlite3
+    dsn imapsql.db
+}
+
+# ----------------------------------------------------------------------------
+# SMTP endpoints + message routing
+
+hostname $(hostname)
+
+msgpipeline local_routing {
+    dmarc yes
+    check {
+        require_mx_record
+        dkim
+        spf
+    }
+
+    # Insert handling for special-purpose local domains here.
+    # e.g.
+    # destination lists.example.org {
+    #     deliver_to lmtp tcp://127.0.0.1:8024
+    # }
+
+    destination postmaster $(local_domains) {
+        modify {
+            replace_rcpt static {
+               entry postmaster           postmaster@$(primary_domain)
+               entry leon@thein.ovh       leah@ctu.cx
+               entry leah@thein.ovh       leah@ctu.cx
+               entry leah@antifa.jetzt    leah@ctu.cx
+            }
+
+            # Implement plus-address notation.
+            replace_rcpt regexp "(.+)\+(.+)@(.+)" "$1@$3"
+
+            replace_rcpt regexp "(.+)@ctucx.de" "leah@ctu.cx"
+            replace_rcpt regexp "(.+)@ctu.cx"   "leah@ctu.cx"
+        }
+
+        deliver_to &local_mailboxes
+    }
+
+    default_destination {
+        reject 550 5.1.1 "User doesn't exist"
+    }
+}
+
+smtp tcp://0.0.0.0:25 {
+    limits {
+        # Up to 20 msgs/sec across max. 10 SMTP connections.
+        all rate 20 1s
+        all concurrency 10
+    }
+
+    source $(local_domains) {
+        reject 501 5.1.8 "Use Submission for outgoing SMTP"
+    }
+
+    default_source {
+        destination postmaster $(local_domains) {
+            deliver_to &local_routing
+        }
+
+        default_destination {
+            reject 550 5.1.1 "User doesn't exist"
+        }
+    }
+}
+
+submission tls://0.0.0.0:465 tcp://0.0.0.0:587 {
+    limits {
+        # Up to 50 msgs/sec across any amount of SMTP connections.
+        all rate 50 1s
+    }
+
+    auth &local_authdb
+
+    source $(local_domains) {
+        destination postmaster $(local_domains) {
+            deliver_to &local_routing
+        }
+
+        default_destination {
+            modify {
+                dkim $(primary_domain) $(local_domains) default {
+                	newkey_algo ed25519
+                }
+            }
+            deliver_to &remote_queue
+        }
+    }
+
+    default_source {
+        reject 501 5.1.8 "Non-local sender domain"
+    }
+}
+
+target.remote outbound_delivery {
+    limits {
+        # Up to 20 msgs/sec across max. 10 SMTP connections
+        # for each recipient domain.
+        destination rate 20 1s
+        destination concurrency 10
+    }
+
+    mx_auth {
+        dane
+
+        mtasts {
+            cache fs
+            fs_dir mtasts_cache/
+        }
+
+        local_policy {
+            min_tls_level encrypted
+            min_mx_level none
+        }
+    }
+}
+
+target.queue remote_queue {
+    target &outbound_delivery
+
+    autogenerated_msg_domain $(primary_domain)
+
+    bounce {
+        destination postmaster $(local_domains) {
+            deliver_to &local_routing
+        }
+
+        default_destination {
+            reject 550 5.0.0 "Refusing to send DSNs to non-local addresses"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------------
+# IMAP endpoints
+
+imap tls://0.0.0.0:993 tcp://0.0.0.0:143 {
+    auth &local_authdb
+    storage &local_mailboxes
+}
diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml
@@ -0,0 +1,59 @@
+---
+
+- name: Install nginx webserver
+  apk:
+   name: nginx
+   state: present
+   update_cache: yes
+
+- name: adding user nginx to group acme-redirect
+  user:
+    name: nginx
+    groups: acme-redirect
+    append: yes
+
+- name: copy nginx config to destination host
+  copy:
+    src: config-files/nginx/nginx.conf
+    dest: /etc/nginx/nginx.conf
+    owner: nginx
+    group: nginx
+
+- name: copy ssl config to destination host
+  copy:
+    src: config-files/nginx/ssl.conf
+    dest: /etc/nginx/ssl.conf
+    owner: nginx
+    group: nginx
+
+- name: copy default vhost to destination host 
+  template:
+    src: vhost.conf.j2
+    dest: /etc/nginx/conf.d/default.conf
+    owner: nginx
+    group: nginx
+
+- name: Copy http(s) firewall-rule to destination host
+  copy:
+    src: config-files/awall/web.json
+    dest: /etc/awall/optional/web.json
+    validate: jq '.' %s
+
+- awall:
+   name: web
+   state: enabled
+   activate: yes
+
+- name: Download dh-params from mozilla
+  get_url:
+    url: https://ssl-config.mozilla.org/ffdhe2048.txt
+    dest: /etc/nginx/dhparam
+    owner: nginx
+    group: nginx    
+
+- name: Enable and start nginx webserver
+  service:
+   name: nginx
+   enabled: yes
+   state: restarted
+
diff --git a/roles/nginx/templates/vhost.conf.j2 b/roles/nginx/templates/vhost.conf.j2
@@ -0,0 +1,22 @@
+server {
+	listen 443 ssl default_server;
+	listen [::]:443 ssl default_server;
+
+	ssl_certificate "{{nginx.ssl_cert}}";
+	ssl_certificate_key "{{nginx.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+
+	# Everything is a 404
+	location / {
+		return 404;
+	}
+
+	location /node-exporter {
+		proxy_pass http://127.0.0.1:9100/metrics;
+	}
+
+	# You may need this to prevent return 404 recursion.
+	location = /404.html {
+		internal;
+	}
+}
diff --git a/roles/oeffisearch/tasks/main.yml b/roles/oeffisearch/tasks/main.yml
@@ -0,0 +1,25 @@
+---
+
+- name: Install oeffisearch
+  apk:
+   name: oeffisearch
+   state: present
+   update_cache: yes
+
+- service:
+   name: oeffisearch
+   enabled: yes
+   state: restarted
+
+- name: copy nginx-vhost for oeffisearch to destination host 
+  template: 
+    src: oeffisearch-vhost.conf.j2
+    dest: /etc/nginx/conf.d/oeffisearch.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted
diff --git a/roles/oeffisearch/templates/oeffisearch-vhost.conf.j2 b/roles/oeffisearch/templates/oeffisearch-vhost.conf.j2
@@ -0,0 +1,19 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{oeffisearch.ssl_cert}}";
+	ssl_certificate_key "{{oeffisearch.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{oeffisearch.domain}};
+
+	location / {
+		try_files $uri $uri/ @api;
+		root /usr/share/oeffisearch;
+	}
+
+	location @api {
+		proxy_pass http://127.0.0.1:8081;
+	}
+}
diff --git a/roles/pleroma/tasks/main.yml b/roles/pleroma/tasks/main.yml
@@ -0,0 +1,71 @@
+---
+
+- name: Install dependencys of pleroma
+  apk:
+   name: curl unzip ncurses
+   state: present
+   update_cache: yes
+
+- name: Install optional dependencys
+  apk:
+   name: imagemagick ffmpeg exiftool
+   state: present
+   update_cache: yes  
+
+- name: Install postgres
+  apk:
+   name: postgresql postgresql-contrib
+   state: present
+   update_cache: yes  
+
+- name: create pleroma group
+  group:
+    name: pleroma
+    state: present
+
+- name: create pleroma user
+  user:
+    name: pleroma
+    create_home: no
+    home: /opt/pleroma
+    shell: /bin/false
+    group: pleroma
+    system: yes
+
+- file:
+    path=/opt/pleroma
+    state=absent
+
+- name: crate required directorys
+  file:
+    path: "{{ item }}"
+    state: directory
+    mode: 0755
+    owner: pleroma
+    group: pleroma
+  loop:
+    - /opt/pleroma
+    - /var/lib/pleroma
+    - /var/lib/pleroma/uploads
+    - /var/lib/pleroma/static
+    - /etc/pleroma
+
+- name: get and unpack pleroma
+  unarchive:
+    remote_src: yes
+    src: "http://home.f2k1.de:8080/pleroma.tar.gz"
+    dest: /opt/pleroma
+    owner: pleroma
+    group: pleroma
+
+- name: copy service file into place 
+  copy: 
+    remote_src: yes
+    src: /opt/pleroma/installation/init.d/pleroma
+    dest: /etc/init.d/pleroma
+    mode: 755
+
+- service:
+   name: postgresql
+   enabled: yes
+   state: restarted
diff --git a/roles/prometheus/tasks/main.yml b/roles/prometheus/tasks/main.yml
@@ -0,0 +1,39 @@
+---
+
+- name: Install prometheus
+  apk:
+   name: prometheus chartsrv
+   state: present
+   update_cache: yes
+
+- name: copy prometheus-config to destination host 
+  copy: 
+    src: config-files/prometheus/prometheus.yml
+    dest: /etc/prometheus/prometheus.yml
+
+- name: copy chartsrv-config to destination host
+  copy:
+    content: 'chartsrv_opts="http://localhost:9090"'
+    dest: /etc/conf.d/chartsrv
+
+- name: copy nginx-vhost for prometheus to destination host
+  template:
+    src: prometheus-vhost.conf.j2
+    dest: /etc/nginx/conf.d/prometheus.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- service:
+   name: prometheus
+   enabled: yes
+   state: restarted
+
+- service:
+   name: chartsrv
+   enabled: yes
+   state: restarted
+
+- service:
+   name: nginx
+   state: restarted
diff --git a/roles/prometheus/templates/prometheus-vhost.conf.j2 b/roles/prometheus/templates/prometheus-vhost.conf.j2
@@ -0,0 +1,19 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{prometheus.ssl_cert}}";
+	ssl_certificate_key "{{prometheus.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{prometheus.domain}};
+
+
+	location / {
+		proxy_pass http://127.0.0.1:9090;
+	}
+
+	location /chart.svg {
+		proxy_pass http://127.0.0.1:8142/chart.svg;
+	}
+}
diff --git a/roles/radicale/tasks/main.yml b/roles/radicale/tasks/main.yml
@@ -0,0 +1,40 @@
+---
+
+- name: Install radicale
+  apk:
+   name: radicale
+   state: present
+   update_cache: yes
+
+- name: copy radicale-config to destination host 
+  copy: 
+    src: config-files/radicale/config
+    dest: /etc/radicale/config
+    mode: 0640
+    owner: root
+    group: radicale
+
+- name: copy radicale-users to destination host
+  copy: 
+    src: secrets/radicale/users
+    dest: /etc/radicale/users
+    mode: 0640
+    owner: root
+    group: radicale
+
+- name: copy nginx-vhost for radicale to destination host
+  template:
+    src: radicale-vhost.conf.j2
+    dest: /etc/nginx/conf.d/radicale.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- service:
+   name: radicale
+   enabled: yes
+   state: restarted
+
+- service:
+   name: nginx
+   state: restarted
diff --git a/roles/radicale/templates/radicale-vhost.conf.j2 b/roles/radicale/templates/radicale-vhost.conf.j2
@@ -0,0 +1,18 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{radicale.ssl_cert}}";
+	ssl_certificate_key "{{radicale.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{radicale.domain}};
+
+
+	location / {
+		proxy_pass       http://localhost:5232/; # The / is important!
+		proxy_set_header Host $host;
+		proxy_set_header X-Real-IP $remote_addr;
+		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+	}
+}
diff --git a/roles/synapse/tasks/main.yml b/roles/synapse/tasks/main.yml
@@ -0,0 +1,51 @@
+---
+
+- name: Install synapse
+  apk:
+   name: synapse riot-web
+   state: present
+   update_cache: yes
+
+- name: copy configs to destination host
+  copy:
+    src: "config-files/synapse/{{ item }}"
+    dest: "/etc/synapse/{{ item }}"
+    mode: 0755
+    owner: synapse
+    group: synapse
+  loop:
+    - homeserver.yaml
+    - log.yaml
+
+- name: copy riot-web config to destination host
+  copy:
+    src: "config-files/riot-web/config.json"
+    dest: "/etc/riot-web/config.json"
+    mode: 0644
+
+- name: create log directory
+  file: 
+    path: "/var/log/synapse"
+    state: directory
+    mode: 0755
+    owner: synapse
+    group: synapse
+
+- name: copy nginx-vhost for synapse to destination host 
+  template: 
+    src: synapse-vhost.conf.j2
+    dest: /etc/nginx/conf.d/synapse.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- name: Enable and start synapse
+  service:
+   name: synapse
+   enabled: yes
+   state: restarted
+
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted
diff --git a/roles/synapse/templates/synapse-vhost.conf.j2 b/roles/synapse/templates/synapse-vhost.conf.j2
@@ -0,0 +1,20 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{synapse.ssl_cert}}";
+	ssl_certificate_key "{{synapse.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{synapse.domain}};
+
+	location /_matrix {
+		proxy_pass http://127.0.0.1:8008;
+		proxy_set_header X-Forwarded-For $remote_addr;
+		client_max_body_size 100M;
+	}
+
+	location / {
+		root /usr/share/webapps/riot-web;
+	}
+}
diff --git a/roles/syncthing/tasks/main.yml b/roles/syncthing/tasks/main.yml
@@ -0,0 +1,41 @@
+---
+
+- name: Install syncthing
+  apk:
+   name: syncthing
+   state: present
+   update_cache: yes
+
+- name: copy initd to destination host 
+  copy: 
+    src: config-files/syncthing/syncthing.initd
+    dest: /etc/init.d/syncthing-leah
+    mode: 0755
+
+- name: Copy syncthing firewall-rule to destination host
+  copy:
+    src: config-files/awall/syncthing.json
+    dest: /etc/awall/optional/syncthing.json
+    validate: jq '.' %s
+
+- name: copy nginx-vhost for syncthing to destination host
+  template:
+    src: syncthing-vhost.conf.j2
+    dest: /etc/nginx/conf.d/syncthing.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- awall:
+   name: syncthing
+   state: enabled
+   activate: yes
+
+- service:
+   name: syncthing-leah
+   enabled: yes
+   state: restarted
+
+- service:
+   name: nginx
+   state: restarted
diff --git a/roles/syncthing/templates/syncthing-vhost.conf.j2 b/roles/syncthing/templates/syncthing-vhost.conf.j2
@@ -0,0 +1,16 @@
+server {
+	listen 443 ssl;
+	listen [::]:443 ssl;
+
+	ssl_certificate "{{syncthing.ssl_cert}}";
+	ssl_certificate_key "{{syncthing.ssl_privkey}}";
+	include /etc/nginx/ssl.conf;
+	
+	server_name {{syncthing.domain}};
+
+
+	location / {
+		proxy_pass       http://localhost:8384/;
+		proxy_set_header Host localhost;
+	}
+}
diff --git a/roles/websites/tasks/ctu.cx.yml b/roles/websites/tasks/ctu.cx.yml
@@ -0,0 +1,21 @@
+---
+
+- name: create root directroy for ctu.cx
+  file:
+    path: /var/lib/websites/ctu.cx
+    state: directory
+    owner: leah
+    group: nginx
+
+- name: copy vhost for ctu.cx into place
+  copy:
+    src: config-files/website-vhosts/ctu.cx.conf
+    dest: /etc/nginx/conf.d/ctu.cx.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted
diff --git a/roles/websites/tasks/main.yml b/roles/websites/tasks/main.yml
@@ -0,0 +1,10 @@
+---
+- include: ctu.cx.yml
+  tags:
+    - install_ctu.cx
+  when: network.hostname == "wanderduene"
+
+- include: photos.ctu.cx.yml
+  tags:
+    - install_photos.ctu.cx
+  when: network.hostname == "taurus"
diff --git a/roles/websites/tasks/photos.ctu.cx.yml b/roles/websites/tasks/photos.ctu.cx.yml
@@ -0,0 +1,21 @@
+---
+
+- name: create root directroy for photos.ctu.cx
+  file:
+    path: /var/lib/websites/photos.ctu.cx
+    state: directory
+    owner: leah
+    group: nginx
+
+- name: copy vhost for photos.ctu.cx into place
+  copy:
+    src: config-files/website-vhosts/photos.ctu.cx.conf
+    dest: /etc/nginx/conf.d/photos.ctu.cx.conf
+    mode: 0644
+    owner: nginx
+    group: nginx
+
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted