sisyphi 1.1.19 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deploy/aws/main.tf +121 -0
- package/deploy/aws/outputs.tf +18 -0
- package/deploy/aws/variables.tf +69 -0
- package/deploy/aws/versions.tf +16 -0
- package/deploy/hetzner/.terraform.lock.hcl +23 -0
- package/deploy/hetzner/main.tf +69 -0
- package/deploy/hetzner/outputs.tf +18 -0
- package/deploy/hetzner/variables.tf +57 -0
- package/deploy/hetzner/versions.tf +15 -0
- package/deploy/shared/bin/pbcopy-shim +5 -0
- package/deploy/shared/bin/pbpaste-shim +4 -0
- package/deploy/shared/cloud-init.yaml.tpl +122 -0
- package/deploy/shared/sisyphusd.service.tpl +17 -0
- package/deploy/shared/tmux-osc52.conf +10 -0
- package/dist/cli.js +3681 -310
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +3863 -474
- package/dist/daemon.js.map +1 -1
- package/dist/deploy/aws/main.tf +121 -0
- package/dist/deploy/aws/outputs.tf +18 -0
- package/dist/deploy/aws/variables.tf +69 -0
- package/dist/deploy/aws/versions.tf +16 -0
- package/dist/deploy/hetzner/.terraform.lock.hcl +23 -0
- package/dist/deploy/hetzner/main.tf +69 -0
- package/dist/deploy/hetzner/outputs.tf +18 -0
- package/dist/deploy/hetzner/variables.tf +57 -0
- package/dist/deploy/hetzner/versions.tf +15 -0
- package/dist/deploy/shared/bin/pbcopy-shim +5 -0
- package/dist/deploy/shared/bin/pbpaste-shim +4 -0
- package/dist/deploy/shared/cloud-init.yaml.tpl +122 -0
- package/dist/deploy/shared/sisyphusd.service.tpl +17 -0
- package/dist/deploy/shared/tmux-osc52.conf +10 -0
- package/dist/tui.js +2915 -185
- package/dist/tui.js.map +1 -1
- package/native/build-notify.sh +23 -0
- package/package.json +4 -3
- package/dist/chunk-36VJ7ZBD.js +0 -1898
- package/dist/chunk-36VJ7ZBD.js.map +0 -1
- package/dist/chunk-M6Z3KHOH.js +0 -1165
- package/dist/chunk-M6Z3KHOH.js.map +0 -1
- package/dist/chunk-O4ZHSQ5R.js +0 -544
- package/dist/chunk-O4ZHSQ5R.js.map +0 -1
- package/dist/chunk-P2HHTIPM.js +0 -478
- package/dist/chunk-P2HHTIPM.js.map +0 -1
- package/dist/chunk-PNDCVKBN.js +0 -201
- package/dist/chunk-PNDCVKBN.js.map +0 -1
- package/dist/chunk-SVGIQ2G4.js +0 -1076
- package/dist/chunk-SVGIQ2G4.js.map +0 -1
- package/dist/paths-JXFLR5BN.js +0 -102
- package/dist/paths-JXFLR5BN.js.map +0 -1
- package/dist/single-ask-6G4BIVY2.js +0 -132
- package/dist/single-ask-6G4BIVY2.js.map +0 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
locals {
|
|
2
|
+
default_sizes = {
|
|
3
|
+
arm = "t4g.medium"
|
|
4
|
+
x86 = "t3.medium"
|
|
5
|
+
}
|
|
6
|
+
resolved_size = var.size != "" ? var.size : local.default_sizes[var.arch]
|
|
7
|
+
|
|
8
|
+
ami_arch = var.arch == "arm" ? "arm64" : "amd64"
|
|
9
|
+
|
|
10
|
+
user_data = templatefile("${path.module}/../shared/cloud-init.yaml.tpl", {
|
|
11
|
+
ssh_pubkey = var.ssh_pubkey
|
|
12
|
+
ts_authkey = var.ts_authkey
|
|
13
|
+
hostname = var.name
|
|
14
|
+
sisyphus_version = var.sisyphus_version
|
|
15
|
+
with_chromium = var.with_chromium
|
|
16
|
+
enable_auto_update = var.enable_auto_update
|
|
17
|
+
sisyphusd_unit = file("${path.module}/../shared/sisyphusd.service.tpl")
|
|
18
|
+
tmux_osc52_conf = file("${path.module}/../shared/tmux-osc52.conf")
|
|
19
|
+
pbcopy_shim = file("${path.module}/../shared/bin/pbcopy-shim")
|
|
20
|
+
pbpaste_shim = file("${path.module}/../shared/bin/pbpaste-shim")
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Canonical Ubuntu 24.04 LTS AMI matching the requested arch.
|
|
25
|
+
data "aws_ami" "ubuntu" {
|
|
26
|
+
most_recent = true
|
|
27
|
+
owners = ["099720109477"] # Canonical
|
|
28
|
+
|
|
29
|
+
filter {
|
|
30
|
+
name = "name"
|
|
31
|
+
values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-${local.ami_arch}-server-*"]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
filter {
|
|
35
|
+
name = "virtualization-type"
|
|
36
|
+
values = ["hvm"]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Default VPC + subnet when not overridden.
|
|
41
|
+
data "aws_vpc" "selected" {
|
|
42
|
+
count = var.vpc_id == "" ? 1 : 0
|
|
43
|
+
default = true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
data "aws_subnets" "selected" {
|
|
47
|
+
count = var.vpc_id == "" && var.subnet_id == "" ? 1 : 0
|
|
48
|
+
filter {
|
|
49
|
+
name = "vpc-id"
|
|
50
|
+
values = [data.aws_vpc.selected[0].id]
|
|
51
|
+
}
|
|
52
|
+
filter {
|
|
53
|
+
name = "default-for-az"
|
|
54
|
+
values = ["true"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
locals {
|
|
59
|
+
effective_vpc_id = var.vpc_id == "" ? data.aws_vpc.selected[0].id : var.vpc_id
|
|
60
|
+
effective_subnet_id = var.subnet_id != "" ? var.subnet_id : data.aws_subnets.selected[0].ids[0]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
resource "aws_key_pair" "this" {
|
|
64
|
+
key_name = "${var.name}-deploy"
|
|
65
|
+
public_key = var.ssh_pubkey
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
resource "aws_security_group" "this" {
|
|
69
|
+
name = "${var.name}-sisyphus"
|
|
70
|
+
description = "sisyphus deploy: deny public 22, allow Tailscale UDP 41641 + ICMP"
|
|
71
|
+
vpc_id = local.effective_vpc_id
|
|
72
|
+
|
|
73
|
+
# Tailscale WireGuard endpoint discovery. SG only sees public traffic
|
|
74
|
+
# on eth0; tailscale0 traffic is userspace and bypasses the SG.
|
|
75
|
+
ingress {
|
|
76
|
+
from_port = 41641
|
|
77
|
+
to_port = 41641
|
|
78
|
+
protocol = "udp"
|
|
79
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
80
|
+
description = "Tailscale WireGuard"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ingress {
|
|
84
|
+
from_port = -1
|
|
85
|
+
to_port = -1
|
|
86
|
+
protocol = "icmp"
|
|
87
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
88
|
+
description = "ICMP for ping debugging"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
egress {
|
|
92
|
+
from_port = 0
|
|
93
|
+
to_port = 0
|
|
94
|
+
protocol = "-1"
|
|
95
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
tags = {
|
|
99
|
+
"managed-by" = "sisyphus-deploy"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
resource "aws_instance" "this" {
|
|
104
|
+
ami = data.aws_ami.ubuntu.id
|
|
105
|
+
instance_type = local.resolved_size
|
|
106
|
+
subnet_id = local.effective_subnet_id
|
|
107
|
+
vpc_security_group_ids = [aws_security_group.this.id]
|
|
108
|
+
key_name = aws_key_pair.this.key_name
|
|
109
|
+
associate_public_ip_address = true
|
|
110
|
+
user_data = local.user_data
|
|
111
|
+
|
|
112
|
+
root_block_device {
|
|
113
|
+
volume_size = 30
|
|
114
|
+
volume_type = "gp3"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
tags = {
|
|
118
|
+
Name = var.name
|
|
119
|
+
"managed-by" = "sisyphus-deploy"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
output "ipv4" {
|
|
2
|
+
value = aws_instance.this.public_ip
|
|
3
|
+
description = "Public IPv4 (firewalled — only Tailscale UDP + ICMP reach the box)."
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "tailscale_hostname" {
|
|
7
|
+
value = var.name
|
|
8
|
+
description = "Tailscale node name. The full MagicDNS hostname is <name>.<your-tailnet>.ts.net once the node joins."
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "ssh_command" {
|
|
12
|
+
value = "ssh sisyphus@${var.name}"
|
|
13
|
+
description = "SSH command via Tailscale MagicDNS (works once the node has joined the tailnet)."
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
output "instance_type" {
|
|
17
|
+
value = aws_instance.this.instance_type
|
|
18
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
variable "name" {
|
|
2
|
+
type = string
|
|
3
|
+
default = "sisyphus"
|
|
4
|
+
description = "Hostname / Tailscale node name. Also used for tagging."
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
variable "region" {
|
|
8
|
+
type = string
|
|
9
|
+
default = "us-east-1"
|
|
10
|
+
description = "AWS region (e.g. us-east-1, eu-west-1)."
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
variable "arch" {
|
|
14
|
+
type = string
|
|
15
|
+
default = "arm"
|
|
16
|
+
description = "CPU arch family: 'arm' (default t4g.medium) or 'x86' (default t3.medium). Drives AMI selection."
|
|
17
|
+
|
|
18
|
+
validation {
|
|
19
|
+
condition = contains(["arm", "x86"], var.arch)
|
|
20
|
+
error_message = "arch must be 'arm' or 'x86'."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
variable "size" {
|
|
25
|
+
type = string
|
|
26
|
+
default = ""
|
|
27
|
+
description = "EC2 instance type. If empty, picks t4g.medium for arm / t3.medium for x86."
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
variable "ssh_pubkey" {
|
|
31
|
+
type = string
|
|
32
|
+
description = "SSH public key to authorize."
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
variable "ts_authkey" {
|
|
36
|
+
type = string
|
|
37
|
+
sensitive = true
|
|
38
|
+
description = "Tailscale auth key (ephemeral, single-use, tagged) — minted by sisyphus deploy runner."
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
variable "sisyphus_version" {
|
|
42
|
+
type = string
|
|
43
|
+
default = "latest"
|
|
44
|
+
description = "npm dist-tag or version of sisyphi to install."
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
variable "with_chromium" {
|
|
48
|
+
type = bool
|
|
49
|
+
default = true
|
|
50
|
+
description = "Install headless Chromium + Playwright deps."
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
variable "enable_auto_update" {
|
|
54
|
+
type = bool
|
|
55
|
+
default = true
|
|
56
|
+
description = "Enable daily auto-update systemd timer."
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
variable "vpc_id" {
|
|
60
|
+
type = string
|
|
61
|
+
default = ""
|
|
62
|
+
description = "VPC ID. Empty → use the account's default VPC."
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
variable "subnet_id" {
|
|
66
|
+
type = string
|
|
67
|
+
default = ""
|
|
68
|
+
description = "Subnet ID. Empty → pick the first default subnet in the VPC."
|
|
69
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_version = ">= 1.5"
|
|
3
|
+
|
|
4
|
+
required_providers {
|
|
5
|
+
aws = {
|
|
6
|
+
source = "hashicorp/aws"
|
|
7
|
+
version = "~> 5.70"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
provider "aws" {
|
|
13
|
+
region = var.region
|
|
14
|
+
# AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars are loaded by the
|
|
15
|
+
# sisyphus deploy runner from ~/.sisyphus/deploy/aws.env.
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# This file is maintained automatically by "terraform init".
|
|
2
|
+
# Manual edits may be lost in future updates.
|
|
3
|
+
|
|
4
|
+
provider "registry.terraform.io/hetznercloud/hcloud" {
|
|
5
|
+
version = "1.62.0"
|
|
6
|
+
constraints = "~> 1.48"
|
|
7
|
+
hashes = [
|
|
8
|
+
"h1:DxU9137L3RD43MlvGD+NQelGCnB02Mv8dtQsBtAzZlw=",
|
|
9
|
+
"zh:2077f1655b6a7e26ae6d8ce3b5f35a6a65728416deb16dbd5165115da7534f37",
|
|
10
|
+
"zh:2234db7b84efa489b8e5f29f756cfed4a5bab760985f62d38c4b9ed2b3d6b4b6",
|
|
11
|
+
"zh:4abee7212fd15bcbf22b156ff18933f3975f2b1153fd3e93a1cacf31b9d35137",
|
|
12
|
+
"zh:5d7a63a8d4c73babea715c0c7a5dc04a08b5076e2f1f59855bf61f2393017bf0",
|
|
13
|
+
"zh:5ef15b4367c139b18167b2169421cb1f760d485db42f05ef292bd63eadcfa802",
|
|
14
|
+
"zh:62b432d918815812ea35ceca252d0ea833a8e1dbbc72c6b2d410369d7b8b0d85",
|
|
15
|
+
"zh:63fd3d3803a86447f9a1c0c49bffe704168fbc907ea3688cfd847e1dd012e9ff",
|
|
16
|
+
"zh:6a84f7125dad475f939afb58a1f0ec089e835d1b30ca64f467d85565a89f7508",
|
|
17
|
+
"zh:834c2ddcaa986323ecb7aa2baa3fd7b1888c2aec249f296822e53a4bc46be66e",
|
|
18
|
+
"zh:887e503de3720894eb756bcfc67b3d8ceb68564f9f8bb2a115d7398f0b5990b7",
|
|
19
|
+
"zh:976216f9aa89a466a1d97ae776c4df2edbac4a9ab29ff9850884060d15024570",
|
|
20
|
+
"zh:c3d7fc02e0fdf1bbee3a07c9171281a59d79ad9df2ec04342a81f3875709171c",
|
|
21
|
+
"zh:e0165f404357f2c1f89524165f38c88f643fb518483adfbf7817a6033a83f4d8",
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
locals {
|
|
2
|
+
default_sizes = {
|
|
3
|
+
arm = "cax11"
|
|
4
|
+
x86 = "cx22"
|
|
5
|
+
}
|
|
6
|
+
resolved_size = var.size != "" ? var.size : local.default_sizes[var.arch]
|
|
7
|
+
|
|
8
|
+
# Hetzner image names: ubuntu-24.04 covers both arch families; the API
|
|
9
|
+
# picks the matching arch based on the server type.
|
|
10
|
+
image = "ubuntu-24.04"
|
|
11
|
+
|
|
12
|
+
user_data = templatefile("${path.module}/../shared/cloud-init.yaml.tpl", {
|
|
13
|
+
ssh_pubkey = var.ssh_pubkey
|
|
14
|
+
ts_authkey = var.ts_authkey
|
|
15
|
+
hostname = var.name
|
|
16
|
+
sisyphus_version = var.sisyphus_version
|
|
17
|
+
with_chromium = var.with_chromium
|
|
18
|
+
enable_auto_update = var.enable_auto_update
|
|
19
|
+
sisyphusd_unit = file("${path.module}/../shared/sisyphusd.service.tpl")
|
|
20
|
+
tmux_osc52_conf = file("${path.module}/../shared/tmux-osc52.conf")
|
|
21
|
+
pbcopy_shim = file("${path.module}/../shared/bin/pbcopy-shim")
|
|
22
|
+
pbpaste_shim = file("${path.module}/../shared/bin/pbpaste-shim")
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resource "hcloud_ssh_key" "this" {
|
|
27
|
+
name = var.name
|
|
28
|
+
public_key = var.ssh_pubkey
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resource "hcloud_firewall" "this" {
|
|
32
|
+
name = "${var.name}-public"
|
|
33
|
+
|
|
34
|
+
# Tailscale runs over WireGuard (UDP 41641) — must reach the public
|
|
35
|
+
# internet to hand off to peers. Once tailnet is up, all sisyphus
|
|
36
|
+
# traffic flows over tailscale0; the box is otherwise unreachable.
|
|
37
|
+
rule {
|
|
38
|
+
direction = "in"
|
|
39
|
+
protocol = "udp"
|
|
40
|
+
port = "41641"
|
|
41
|
+
source_ips = ["0.0.0.0/0", "::/0"]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# ICMP for ping debugging (optional; keep it open).
|
|
45
|
+
rule {
|
|
46
|
+
direction = "in"
|
|
47
|
+
protocol = "icmp"
|
|
48
|
+
source_ips = ["0.0.0.0/0", "::/0"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
resource "hcloud_server" "this" {
|
|
53
|
+
name = var.name
|
|
54
|
+
server_type = local.resolved_size
|
|
55
|
+
image = local.image
|
|
56
|
+
location = var.region
|
|
57
|
+
ssh_keys = [hcloud_ssh_key.this.id]
|
|
58
|
+
firewall_ids = [hcloud_firewall.this.id]
|
|
59
|
+
user_data = local.user_data
|
|
60
|
+
|
|
61
|
+
public_net {
|
|
62
|
+
ipv4_enabled = true
|
|
63
|
+
ipv6_enabled = true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
labels = {
|
|
67
|
+
managed-by = "sisyphus-deploy"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
output "ipv4" {
|
|
2
|
+
value = hcloud_server.this.ipv4_address
|
|
3
|
+
description = "Public IPv4 (firewalled — only Tailscale + WireGuard handshake reach the box)."
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "tailscale_hostname" {
|
|
7
|
+
value = var.name
|
|
8
|
+
description = "Tailscale node name. The full MagicDNS hostname is <name>.<your-tailnet>.ts.net once the node joins."
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "ssh_command" {
|
|
12
|
+
value = "ssh sisyphus@${var.name}"
|
|
13
|
+
description = "SSH command via Tailscale MagicDNS (works once the node has joined the tailnet)."
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
output "instance_type" {
|
|
17
|
+
value = hcloud_server.this.server_type
|
|
18
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
variable "name" {
|
|
2
|
+
type = string
|
|
3
|
+
default = "sisyphus"
|
|
4
|
+
description = "Hostname / Tailscale node name."
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
variable "region" {
|
|
8
|
+
type = string
|
|
9
|
+
default = "nbg1"
|
|
10
|
+
description = "Hetzner location (nbg1, fsn1, hel1, ash, hil)."
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
variable "arch" {
|
|
14
|
+
type = string
|
|
15
|
+
default = "arm"
|
|
16
|
+
description = "CPU arch family: 'arm' (default cax11) or 'x86' (default cx22). Ignored if size is set explicitly."
|
|
17
|
+
|
|
18
|
+
validation {
|
|
19
|
+
condition = contains(["arm", "x86"], var.arch)
|
|
20
|
+
error_message = "arch must be 'arm' or 'x86'."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
variable "size" {
|
|
25
|
+
type = string
|
|
26
|
+
default = ""
|
|
27
|
+
description = "Hetzner server type. If empty, picks cax11 for arm / cx22 for x86."
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
variable "ssh_pubkey" {
|
|
31
|
+
type = string
|
|
32
|
+
description = "SSH public key to authorize for root and sisyphus users."
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
variable "ts_authkey" {
|
|
36
|
+
type = string
|
|
37
|
+
sensitive = true
|
|
38
|
+
description = "Tailscale auth key (ephemeral, single-use, tagged) — minted by sisyphus deploy runner."
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
variable "sisyphus_version" {
|
|
42
|
+
type = string
|
|
43
|
+
default = "latest"
|
|
44
|
+
description = "npm dist-tag or version of sisyphi to install."
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
variable "with_chromium" {
|
|
48
|
+
type = bool
|
|
49
|
+
default = true
|
|
50
|
+
description = "Install headless Chromium + Playwright deps."
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
variable "enable_auto_update" {
|
|
54
|
+
type = bool
|
|
55
|
+
default = true
|
|
56
|
+
description = "Enable daily systemd timer that runs `npm i -g sisyphi@latest` and restarts the daemon."
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_version = ">= 1.5"
|
|
3
|
+
|
|
4
|
+
required_providers {
|
|
5
|
+
hcloud = {
|
|
6
|
+
source = "hetznercloud/hcloud"
|
|
7
|
+
version = "~> 1.48"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
provider "hcloud" {
|
|
13
|
+
# HCLOUD_TOKEN env var is loaded by sisyphus deploy runner from
|
|
14
|
+
# ~/.sisyphus/deploy/hetzner.env before invoking terraform.
|
|
15
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#cloud-config
|
|
2
|
+
# Provisioned by `sisyphus deploy` — turns a clean Ubuntu 24.04 box into
|
|
3
|
+
# a Tailscale-only sisyphus host. See specs/deploy.md.
|
|
4
|
+
|
|
5
|
+
hostname: ${hostname}
|
|
6
|
+
fqdn: ${hostname}
|
|
7
|
+
preserve_hostname: false
|
|
8
|
+
|
|
9
|
+
users:
|
|
10
|
+
- name: sisyphus
|
|
11
|
+
groups: [sudo]
|
|
12
|
+
shell: /bin/bash
|
|
13
|
+
sudo: 'ALL=(ALL) NOPASSWD:ALL'
|
|
14
|
+
ssh_authorized_keys:
|
|
15
|
+
- ${ssh_pubkey}
|
|
16
|
+
- name: root
|
|
17
|
+
ssh_authorized_keys:
|
|
18
|
+
- ${ssh_pubkey}
|
|
19
|
+
|
|
20
|
+
write_files:
|
|
21
|
+
- path: /etc/systemd/user/sisyphusd.service
|
|
22
|
+
permissions: '0644'
|
|
23
|
+
content: |
|
|
24
|
+
${indent(6, sisyphusd_unit)}
|
|
25
|
+
|
|
26
|
+
- path: /etc/sisyphus/tmux-osc52.conf
|
|
27
|
+
permissions: '0644'
|
|
28
|
+
content: |
|
|
29
|
+
${indent(6, tmux_osc52_conf)}
|
|
30
|
+
|
|
31
|
+
- path: /usr/local/bin/pbcopy
|
|
32
|
+
permissions: '0755'
|
|
33
|
+
content: |
|
|
34
|
+
${indent(6, pbcopy_shim)}
|
|
35
|
+
|
|
36
|
+
- path: /usr/local/bin/pbpaste
|
|
37
|
+
permissions: '0755'
|
|
38
|
+
content: |
|
|
39
|
+
${indent(6, pbpaste_shim)}
|
|
40
|
+
|
|
41
|
+
- path: /etc/systemd/system/sisyphusd-update.service
|
|
42
|
+
permissions: '0644'
|
|
43
|
+
content: |
|
|
44
|
+
[Unit]
|
|
45
|
+
Description=Sisyphus auto-update
|
|
46
|
+
After=network-online.target
|
|
47
|
+
Wants=network-online.target
|
|
48
|
+
|
|
49
|
+
[Service]
|
|
50
|
+
Type=oneshot
|
|
51
|
+
ExecStart=/bin/sh -c 'npm i -g sisyphi@latest && sudo -u sisyphus XDG_RUNTIME_DIR=/run/user/$(id -u sisyphus) systemctl --user restart sisyphusd'
|
|
52
|
+
|
|
53
|
+
- path: /etc/systemd/system/sisyphusd-update.timer
|
|
54
|
+
permissions: '0644'
|
|
55
|
+
content: |
|
|
56
|
+
[Unit]
|
|
57
|
+
Description=Sisyphus auto-update daily
|
|
58
|
+
|
|
59
|
+
[Timer]
|
|
60
|
+
OnCalendar=daily
|
|
61
|
+
Persistent=true
|
|
62
|
+
RandomizedDelaySec=30min
|
|
63
|
+
|
|
64
|
+
[Install]
|
|
65
|
+
WantedBy=timers.target
|
|
66
|
+
|
|
67
|
+
runcmd:
|
|
68
|
+
# 1. Base packages.
|
|
69
|
+
- apt-get update
|
|
70
|
+
- DEBIAN_FRONTEND=noninteractive apt-get install -y curl git tmux fzf neovim build-essential ufw mosh ca-certificates gnupg
|
|
71
|
+
|
|
72
|
+
# 2. Node 22 via NodeSource. /usr/bin/node, /usr/bin/npm.
|
|
73
|
+
- curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
|
74
|
+
- DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs
|
|
75
|
+
|
|
76
|
+
# 3. Tailscale. We deliberately do NOT pass --ssh: Tailscale SSH would
|
|
77
|
+
# intercept port 22 on the tailscale0 interface and require a browser-
|
|
78
|
+
# based check (per the user's tailnet ACL), blocking key-based access.
|
|
79
|
+
# System OpenSSH on tailscale0 with the user's pubkey is simpler.
|
|
80
|
+
- curl -fsSL https://tailscale.com/install.sh | sh
|
|
81
|
+
- tailscale up --authkey='${ts_authkey}' --hostname='${hostname}'
|
|
82
|
+
|
|
83
|
+
# 4. Firewall. Public 22 stays denied; tailscale0 fully open.
|
|
84
|
+
- ufw default deny incoming
|
|
85
|
+
- ufw default allow outgoing
|
|
86
|
+
- ufw allow in on tailscale0
|
|
87
|
+
- ufw --force enable
|
|
88
|
+
|
|
89
|
+
# 5. Sisyphus user — linger so user systemd survives logout.
|
|
90
|
+
- loginctl enable-linger sisyphus
|
|
91
|
+
- install -d -o sisyphus -g sisyphus -m 0755 /home/sisyphus/.config/systemd/user
|
|
92
|
+
- install -d -o sisyphus -g sisyphus -m 0755 /home/sisyphus/.sisyphus
|
|
93
|
+
- cp /etc/systemd/user/sisyphusd.service /home/sisyphus/.config/systemd/user/sisyphusd.service
|
|
94
|
+
- chown -R sisyphus:sisyphus /home/sisyphus/.config
|
|
95
|
+
|
|
96
|
+
# 6. Sisyphus install (root → /usr/bin/sisyphusd symlink).
|
|
97
|
+
- npm i -g sisyphi@${sisyphus_version}
|
|
98
|
+
|
|
99
|
+
# 7. Daemon as systemd user service.
|
|
100
|
+
- sudo -u sisyphus XDG_RUNTIME_DIR=/run/user/$(id -u sisyphus) systemctl --user daemon-reload
|
|
101
|
+
- sudo -u sisyphus XDG_RUNTIME_DIR=/run/user/$(id -u sisyphus) systemctl --user enable --now sisyphusd
|
|
102
|
+
|
|
103
|
+
# 8. Auto-update timer (system-level so npm i -g has root; restarts user daemon).
|
|
104
|
+
%{ if enable_auto_update ~}
|
|
105
|
+
- systemctl daemon-reload
|
|
106
|
+
- systemctl enable --now sisyphusd-update.timer
|
|
107
|
+
%{ endif ~}
|
|
108
|
+
|
|
109
|
+
# 9. Tmux config (OSC 52 + pbcopy/pbpaste shims already written above).
|
|
110
|
+
- sudo -u sisyphus bash -c 'printf "source-file /etc/sisyphus/tmux-osc52.conf\n" > /home/sisyphus/.tmux.conf'
|
|
111
|
+
- chown sisyphus:sisyphus /home/sisyphus/.tmux.conf
|
|
112
|
+
|
|
113
|
+
# 10. Keybinds. Runs after pbcopy/pbpaste are on PATH so popup scripts resolve them.
|
|
114
|
+
- sudo -u sisyphus -i sisyphus admin setup-keybind || true
|
|
115
|
+
|
|
116
|
+
# 11. Chromium for Playwright/capture (gated).
|
|
117
|
+
%{ if with_chromium ~}
|
|
118
|
+
- DEBIAN_FRONTEND=noninteractive apt-get install -y chromium-browser libxss1 libnss3 libgbm1 libxkbcommon0 libasound2t64 || DEBIAN_FRONTEND=noninteractive apt-get install -y chromium libxss1 libnss3 libgbm1 libxkbcommon0 libasound2
|
|
119
|
+
%{ endif ~}
|
|
120
|
+
|
|
121
|
+
# Done — marker for `sisyphus deploy <provider> up` polling loop.
|
|
122
|
+
- echo "sisyphus cloud-init done" >> /var/log/cloud-init-output.log
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Sisyphus Daemon
|
|
3
|
+
After=network.target
|
|
4
|
+
|
|
5
|
+
[Service]
|
|
6
|
+
Type=simple
|
|
7
|
+
ExecStart=/usr/bin/sisyphusd
|
|
8
|
+
Restart=always
|
|
9
|
+
RestartSec=5
|
|
10
|
+
StandardOutput=append:%h/.sisyphus/daemon.log
|
|
11
|
+
StandardError=append:%h/.sisyphus/daemon.log
|
|
12
|
+
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
13
|
+
Environment=HOME=%h
|
|
14
|
+
WorkingDirectory=%h
|
|
15
|
+
|
|
16
|
+
[Install]
|
|
17
|
+
WantedBy=default.target
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# OSC 52 clipboard round-trip — selections inside tmux escape out to the
|
|
2
|
+
# user's local terminal clipboard via OSC 52, so copy/paste works without
|
|
3
|
+
# any agent on the box. Sourced from ~/.tmux.conf on sisyphus deploy boxes.
|
|
4
|
+
set -g set-clipboard on
|
|
5
|
+
set -ga terminal-overrides ',*:Ms=\E]52;c;%p2%s\7'
|
|
6
|
+
|
|
7
|
+
# Vi-mode copy bindings push to the OSC 52 buffer.
|
|
8
|
+
setw -g mode-keys vi
|
|
9
|
+
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "tmux load-buffer -w -"
|
|
10
|
+
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "tmux load-buffer -w -"
|