Add landing page, Hetzner labels, and Codeberg link
- Add default landing page (roles/caddy/templates/index.html.j2) deployed
to empty caddy sites; adapted from YC/coming-soon by Steven Tang (MIT),
with site domain and powered-by footer linking to codeberg.org/opennomad/linderhof
- Apply hcloud_labels to all Hetzner cloud and DNS resources; default to {}
in role defaults for stacks without the variable defined
- Fix setup.sh: export stack_name so envsubst substitutes it in config.yml
- Add Codeberg repo link to README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bd90a7e16f
commit
e4fdcdc279
8 changed files with 112 additions and 1 deletions
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
> *Linderhof* — the smallest and most intimate of Ludwig II's Bavarian palaces, the only one he lived to see completed; built entirely to his own vision as a private retreat. ([Wikipedia](https://en.wikipedia.org/wiki/Linderhof_Palace))
|
> *Linderhof* — the smallest and most intimate of Ludwig II's Bavarian palaces, the only one he lived to see completed; built entirely to his own vision as a private retreat. ([Wikipedia](https://en.wikipedia.org/wiki/Linderhof_Palace))
|
||||||
|
|
||||||
|
**[codeberg.org/opennomad/linderhof](https://codeberg.org/opennomad/linderhof)**
|
||||||
|
|
||||||
a self-hosting stack based on ansible and docker compose that comes with
|
a self-hosting stack based on ansible and docker compose that comes with
|
||||||
|
|
||||||
- email
|
- email
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,16 @@
|
||||||
mode: "0775" # also allow members of the docker group to write
|
mode: "0775" # also allow members of the docker group to write
|
||||||
loop: "{{ caddy_sites }}"
|
loop: "{{ caddy_sites }}"
|
||||||
|
|
||||||
|
- name: Deploy default landing page for empty sites
|
||||||
|
template:
|
||||||
|
src: index.html.j2
|
||||||
|
dest: "/srv/caddy/sites/{{ item }}/index.html"
|
||||||
|
owner: root
|
||||||
|
group: docker
|
||||||
|
mode: "0644"
|
||||||
|
force: false # never overwrite real content
|
||||||
|
loop: "{{ caddy_sites }}"
|
||||||
|
|
||||||
- name: Install Caddyfile
|
- name: Install Caddyfile
|
||||||
template:
|
template:
|
||||||
src: Caddyfile.j2
|
src: Caddyfile.j2
|
||||||
|
|
|
||||||
86
roles/caddy/templates/index.html.j2
Normal file
86
roles/caddy/templates/index.html.j2
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
{#
|
||||||
|
Adapted from "Coming Soon" by Steven Tang (github.com/YC/coming-soon)
|
||||||
|
MIT License — https://github.com/YC/coming-soon/blob/master/LICENSE
|
||||||
|
#}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{{ item }}</title>
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; }
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
background: #0f1117;
|
||||||
|
color: #e8e8e8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
animation: fadein 2s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: clamp(1.8rem, 5vw, 3rem);
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: clamp(1rem, 2.5vw, 1.25rem);
|
||||||
|
font-weight: 300;
|
||||||
|
color: #a0a0a0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
color: #00b98b;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1.5rem;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
color: #555;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover {
|
||||||
|
color: #00b98b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadein {
|
||||||
|
from { opacity: 0; transform: translateY(12px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>{{ item }}<span class="dot">.</span></h1>
|
||||||
|
<p>Something's on its way.</p>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
powered by <a href="https://codeberg.org/opennomad/linderhof" target="_blank" rel="noopener">linderhof</a>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
---
|
---
|
||||||
dns_zones: []
|
dns_zones: []
|
||||||
|
hcloud_labels: {} # override in config.yml — see config.yml.setup for recommended labels
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "{{ server_ip }}"
|
- value: "{{ server_ip }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "10 {{ mail_hostname }}."
|
- value: "10 {{ mail_hostname }}."
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
|
|
@ -29,6 +31,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "{{ 'v=spf1 mx -all' | hetzner.hcloud.txt_record }}"
|
- value: "{{ 'v=spf1 mx -all' | hetzner.hcloud.txt_record }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
|
|
@ -40,6 +43,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "{{ ('v=DMARC1; p=none; rua=mailto:dmarc@' + extra_domain) | hetzner.hcloud.txt_record }}"
|
- value: "{{ ('v=DMARC1; p=none; rua=mailto:dmarc@' + extra_domain) | hetzner.hcloud.txt_record }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
|
|
@ -51,6 +55,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "{{ dkim_keys[extra_domain] | hetzner.hcloud.txt_record }}"
|
- value: "{{ dkim_keys[extra_domain] | hetzner.hcloud.txt_record }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
when: dkim_keys is defined and extra_domain in dkim_keys
|
when: dkim_keys is defined and extra_domain in dkim_keys
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
hetzner.hcloud.zone:
|
hetzner.hcloud.zone:
|
||||||
name: "{{ item.zone }}"
|
name: "{{ item.zone }}"
|
||||||
mode: primary
|
mode: primary
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
loop: "{{ dns_zones }}"
|
loop: "{{ dns_zones }}"
|
||||||
|
|
@ -17,6 +18,7 @@
|
||||||
type: "{{ item.1.type }}"
|
type: "{{ item.1.type }}"
|
||||||
ttl: "{{ item.1.ttl | default(300) }}"
|
ttl: "{{ item.1.ttl | default(300) }}"
|
||||||
records: "{{ item.1.records }}"
|
records: "{{ item.1.records }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
loop: "{{ dns_zones | subelements('records') }}"
|
loop: "{{ dns_zones | subelements('records') }}"
|
||||||
|
|
@ -29,6 +31,7 @@
|
||||||
hetzner.hcloud.zone:
|
hetzner.hcloud.zone:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
mode: primary
|
mode: primary
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
loop: "{{ mail_domains | difference([domain]) }}"
|
loop: "{{ mail_domains | difference([domain]) }}"
|
||||||
|
|
@ -51,6 +54,7 @@
|
||||||
ttl: 300
|
ttl: 300
|
||||||
records:
|
records:
|
||||||
- value: "{{ item.value | hetzner.hcloud.txt_record }}"
|
- value: "{{ item.value | hetzner.hcloud.txt_record }}"
|
||||||
|
labels: "{{ hcloud_labels }}"
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
state: present
|
state: present
|
||||||
loop: "{{ dkim_keys | default({}) | dict2items }}"
|
loop: "{{ dkim_keys | default({}) | dict2items }}"
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ cloud_provider: hetzner
|
||||||
hcloud_server_type: cx23
|
hcloud_server_type: cx23
|
||||||
hcloud_image: ubuntu-24.04
|
hcloud_image: ubuntu-24.04
|
||||||
hcloud_location: fsn1
|
hcloud_location: fsn1
|
||||||
|
hcloud_labels: {} # override in config.yml — see config.yml.setup for recommended labels
|
||||||
|
|
|
||||||
4
setup.sh
4
setup.sh
|
|
@ -45,6 +45,8 @@ ok "collections installed"
|
||||||
echo
|
echo
|
||||||
info "stack setup"
|
info "stack setup"
|
||||||
prompt stack_name "Stack name" "home"
|
prompt stack_name "Stack name" "home"
|
||||||
|
export stack_name
|
||||||
|
|
||||||
|
|
||||||
LINDERHOF_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/linderhof"
|
LINDERHOF_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/linderhof"
|
||||||
STACK_DIR="$LINDERHOF_CONFIG_DIR/$stack_name"
|
STACK_DIR="$LINDERHOF_CONFIG_DIR/$stack_name"
|
||||||
|
|
@ -174,7 +176,7 @@ if [[ -f "$CONFIG" ]]; then
|
||||||
warn "config.yml already exists — skipping (not overwriting)"
|
warn "config.yml already exists — skipping (not overwriting)"
|
||||||
else
|
else
|
||||||
info "writing config.yml..."
|
info "writing config.yml..."
|
||||||
envsubst '$admin_user $server_name $server_ip $domain $ssh_key_pub' \
|
envsubst '$admin_user $server_name $server_ip $domain $ssh_key_pub $stack_name' \
|
||||||
< "$TEMPLATES/config.yml.setup" > "$CONFIG"
|
< "$TEMPLATES/config.yml.setup" > "$CONFIG"
|
||||||
ok "config.yml created"
|
ok "config.yml created"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue