Skip to main content

max / alloy

6.6 KB · 164 lines History Blame Raw
1 # 12. Network, mesh, sync, and backup
2
3 Alloy assumes the machine is disposable and your state is not. An install
4 should be rejoinable: build the medium, install, sign in to two things, and
5 your files and your other machines are there.
6
7 Both enrollments are opt-in. Nothing connects to anything until you say so.
8
9 ## Wifi and wired networking
10
11 alloy net
12
13 lists interfaces and connections. Connecting, disconnecting, and toggling the
14 wifi radio all work without any privilege, because NetworkManager grants those
15 to an active session.
16
17 Joining a network you have never joined before is a different permission, and
18 the console does not yet ask for it. For a new network:
19
20 run0 nmcli device wifi connect "Network Name" --ask
21
22 Once it is saved, `alloy net` connects to it like any other.
23
24 ## The firewall
25
26 Alloy runs firewalld, on every install and both profiles. Inbound connections
27 are refused unless something allows them; outbound traffic is untouched.
28
29 What is allowed by default on a desktop install is `ssh`, mDNS, and DHCPv6
30 replies. That is the same list as the services Alloy actually runs, which is
31 the point: the firewall is the enforcement of the defaults rather than a
32 separate policy to keep in step with them.
33
34 Printing needs nothing here. CUPS listens on a unix socket and on localhost,
35 and loopback is not filtered.
36
37 To open something you installed yourself:
38
39 run0 firewall-cmd --permanent --add-port=8080/tcp
40 run0 firewall-cmd --reload
41
42 `--add-service=<name>` takes a name from `firewall-cmd --get-services` and is
43 better when one exists, because it carries every port the service needs.
44
45 To see what is currently allowed:
46
47 firewall-cmd --list-all
48
49 **A server image is stricter by one entry.** It allows `ssh` and DHCPv6 and not
50 mDNS, because that profile is also what runs on a machine with a public
51 address, and answering mDNS to the internet buys nothing. If your server is on
52 a LAN and you want to reach it at `<name>.local`:
53
54 run0 firewall-cmd --permanent --add-service=mdns
55 run0 firewall-cmd --reload
56
57 Without it the machine is still findable: it sends its hostname over DHCP, so
58 it appears in the router's lease table under the name it was minted with.
59
60 **The tailnet is exempt.** The `tailscale0` interface is in firewalld's trusted
61 zone, so anything reaching this machine over Tailscale is accepted on any port
62 regardless of the rules above. That is deliberate, and it is worth knowing
63 rather than discovering: a service you start for yourself is reachable by every
64 machine on your tailnet, without opening a port. Access there is controlled by
65 your Tailscale ACL rather than by this firewall.
66
67 ## Mesh: Tailscale
68
69 alloy mesh
70
71 A machine that has not joined anything shows an offer rather than an empty
72 list. Press `e` to set the control server before signing in: leave it empty for
73 tailscale.com, or enter a URL for a self-hosted Headscale.
74
75 Signing in escalates to root and then waits on a browser login, so the console
76 gets out of the way while that happens and comes back into the peer list
77 afterwards.
78
79 Once enrolled, the view lists your peers, whether each is online, when it was
80 last seen, and lets you pick or clear an exit node. This machine is listed
81 first. If you are on a self-hosted control plane, the title says so.
82
83 Anything that acts on the whole tailnet rather than on this machine — deleting
84 a node, editing the ACL, minting an auth key — lives in the admin console and
85 nowhere else. The `tailscale` client has no verb for any of it. `w` opens that
86 console in a browser. On a self-hosted control plane the address is a guess at
87 the control host's root, and the status line says so, because Headscale serves
88 the control API there and no UI.
89
90 The plain command is `run0 tailscale up`, and `alloy tail` is kept as an alias
91 for the verb.
92
93 Alloy does not ship a Headscale server. That is fleet-admin work, not
94 client-OS work.
95
96 ## File sync: Syncthing
97
98 alloy sync
99
100 Three tabs: **folders**, **devices**, and **pending**.
101
102 - Folders shows each synchronized folder's path, share mode, and whether it is
103 paused. `a` adds one, `d` removes one, and both confirms tell you what is
104 *not* deleted, because "remove folder" must never read as "delete my
105 documents". `s` opens the folder's share list, where each device toggles on
106 or off as you press it; this machine is not offered there, because taking it
107 off the list is what `d` does.
108 - Devices shows connection state, this machine first.
109 - Pending lists devices that have added you and are knocking. Accepting one
110 finishes the pairing.
111
112 Enrollment is a user service and needs no root:
113
114 systemctl --user enable --now syncthing.service
115
116 Syncing over the LAN also needs the firewall opened, because Syncthing is off
117 by default and Alloy does not open ports for services nobody is running:
118
119 run0 firewall-cmd --permanent --add-service=syncthing
120 run0 firewall-cmd --reload
121
122 Two machines on the same tailnet need none of that. The tailnet is exempt from
123 the firewall, so they find each other with no rule at all.
124
125 One asymmetry to know about: you can accept a pending device but not decline
126 it. The command-line client Syncthing ships has no verb for dropping a pending
127 entry, so an unaccepted device stays listed. The view says so when you press
128 `d` there.
129
130 Syncthing's own web UI is still at `127.0.0.1:8384` for anything the console
131 does not cover — ignore patterns, versioning, per-folder advanced settings.
132 `w` opens it rather than making you remember the address.
133
134 ## Backup: restic
135
136 restic is in the image and Alloy prescribes no policy. Where you back up to is
137 answerable only by you, so there is no default repository, schedule, or
138 retention.
139
140 This matters more than it looks. Sync is mesh plus latest-wins; it gets your
141 files onto the new machine. It does not get back the file you deleted three
142 weeks ago and only just noticed. That case needs versioned backup, which means
143 configuring restic:
144
145 restic init --repo <destination>
146 restic backup ~/Documents ~/Pictures
147 restic snapshots
148
149 Any of restic's backends work: local disk, SFTP, S3, B2, rclone. A systemd
150 user timer is the usual way to make it recurring.
151
152 There is no `alloy backup` view. It is a candidate, not a plan.
153
154 ## What is deliberately not synced
155
156 - **Secrets.** Too personal, and the security models vary too much for a
157 defensible default. gopass (chapter 10) is the shipped tool, and you decide
158 what it holds and where it goes.
159 - **Dotfiles.** Syncthing can carry `~/.config` and Alloy does not set that up
160 for you.
161 - **The first-boot marker.** Deliberately never replicated: a synced copy would
162 suppress the enrollment screen on the next machine you set up, which is
163 exactly the machine that needs it.
164