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.
Files changed (52) hide show
  1. package/deploy/aws/main.tf +121 -0
  2. package/deploy/aws/outputs.tf +18 -0
  3. package/deploy/aws/variables.tf +69 -0
  4. package/deploy/aws/versions.tf +16 -0
  5. package/deploy/hetzner/.terraform.lock.hcl +23 -0
  6. package/deploy/hetzner/main.tf +69 -0
  7. package/deploy/hetzner/outputs.tf +18 -0
  8. package/deploy/hetzner/variables.tf +57 -0
  9. package/deploy/hetzner/versions.tf +15 -0
  10. package/deploy/shared/bin/pbcopy-shim +5 -0
  11. package/deploy/shared/bin/pbpaste-shim +4 -0
  12. package/deploy/shared/cloud-init.yaml.tpl +122 -0
  13. package/deploy/shared/sisyphusd.service.tpl +17 -0
  14. package/deploy/shared/tmux-osc52.conf +10 -0
  15. package/dist/cli.js +3681 -310
  16. package/dist/cli.js.map +1 -1
  17. package/dist/daemon.js +3863 -474
  18. package/dist/daemon.js.map +1 -1
  19. package/dist/deploy/aws/main.tf +121 -0
  20. package/dist/deploy/aws/outputs.tf +18 -0
  21. package/dist/deploy/aws/variables.tf +69 -0
  22. package/dist/deploy/aws/versions.tf +16 -0
  23. package/dist/deploy/hetzner/.terraform.lock.hcl +23 -0
  24. package/dist/deploy/hetzner/main.tf +69 -0
  25. package/dist/deploy/hetzner/outputs.tf +18 -0
  26. package/dist/deploy/hetzner/variables.tf +57 -0
  27. package/dist/deploy/hetzner/versions.tf +15 -0
  28. package/dist/deploy/shared/bin/pbcopy-shim +5 -0
  29. package/dist/deploy/shared/bin/pbpaste-shim +4 -0
  30. package/dist/deploy/shared/cloud-init.yaml.tpl +122 -0
  31. package/dist/deploy/shared/sisyphusd.service.tpl +17 -0
  32. package/dist/deploy/shared/tmux-osc52.conf +10 -0
  33. package/dist/tui.js +2915 -185
  34. package/dist/tui.js.map +1 -1
  35. package/native/build-notify.sh +23 -0
  36. package/package.json +4 -3
  37. package/dist/chunk-36VJ7ZBD.js +0 -1898
  38. package/dist/chunk-36VJ7ZBD.js.map +0 -1
  39. package/dist/chunk-M6Z3KHOH.js +0 -1165
  40. package/dist/chunk-M6Z3KHOH.js.map +0 -1
  41. package/dist/chunk-O4ZHSQ5R.js +0 -544
  42. package/dist/chunk-O4ZHSQ5R.js.map +0 -1
  43. package/dist/chunk-P2HHTIPM.js +0 -478
  44. package/dist/chunk-P2HHTIPM.js.map +0 -1
  45. package/dist/chunk-PNDCVKBN.js +0 -201
  46. package/dist/chunk-PNDCVKBN.js.map +0 -1
  47. package/dist/chunk-SVGIQ2G4.js +0 -1076
  48. package/dist/chunk-SVGIQ2G4.js.map +0 -1
  49. package/dist/paths-JXFLR5BN.js +0 -102
  50. package/dist/paths-JXFLR5BN.js.map +0 -1
  51. package/dist/single-ask-6G4BIVY2.js +0 -132
  52. 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,5 @@
1
+ #!/bin/sh
2
+ # pbcopy compatibility shim for Linux. Loads stdin into the tmux paste
3
+ # buffer and pushes via OSC 52 (-w) so the selection escapes out to the
4
+ # user's local terminal clipboard. Requires an active tmux session.
5
+ exec tmux load-buffer -w -
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # pbpaste compatibility shim for Linux. Emits the current tmux paste
3
+ # buffer to stdout. Requires an active tmux session.
4
+ exec tmux save-buffer -
@@ -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 -"