@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1@title Diffusion User Guide: Repository Hosting
2@group userguide
3
4Guide to configuring Phorge repository hosting.
5
6Overview
7========
8
9Phorge can host repositories and provide authenticated read and write
10access to them over HTTP and SSH. This document describes how to configure
11repository hosting.
12
13Understanding Supported Protocols
14=================================
15
16Phorge supports hosting over these protocols:
17
18| VCS | SSH | HTTP |
19|-----|-----|------|
20| Git | Supported | Supported |
21| Mercurial | Supported | Supported |
22| Subversion | Supported | Not Supported |
23
24All supported protocols handle reads (pull/checkout/clone) and writes
25(push/commit). Of the two protocols, SSH is generally more robust, secure and
26performant, but HTTP is easier to set up and supports anonymous access.
27
28| | SSH | HTTP |
29| |-----|------|
30| Reads | Yes | Yes |
31| Writes | Yes | Yes |
32| Authenticated Access | Yes | Yes |
33| Push Logs | Yes | Yes |
34| Commit Hooks | Yes | Yes |
35| Anonymous Access | No | Yes |
36| Security | Better (Asymmetric Key) | Okay (Password) |
37| Performance | Better | Okay |
38| Setup | Hard | Easy |
39
40Each repository can be configured individually, and you can use either
41protocol, or both, or a mixture across different repositories.
42
43SSH is recommended unless you need anonymous access, or are not able to
44configure it for technical reasons.
45
46
47Creating System User Accounts
48=============================
49
50Phorge uses two system user accounts, plus a third account if you
51configure SSH access. This section will guide you through creating and
52configuring them. These are system user accounts on the machine Phorge
53runs on, not Phorge user accounts.
54
55The system accounts Phorge uses are:
56
57 - The user the webserver runs as. We'll call this `www-user`.
58 - The user the daemons run as. We'll call this `daemon-user`. This
59 user is the only user which will interact with the repositories directly.
60 Other accounts will `sudo` to this account in order to perform repository
61 operations.
62 - The user that humans will connect over SSH as. We'll call this `vcs-user`.
63 If you do not plan to make repositories available over SSH, you do not need
64 to create or configure this user.
65
66IMPORTANT: As a general service management philosophy, service users are
67virtually always named after the service they are for. You are **strongly**
68encouraged to pick something other than `daemon-user` for running the daemons. A
69good username might be `phd`.
70
71To create these users:
72
73 - Create a `www-user` if one does not already exist. In most cases, this
74 user will already exist and you just need to identify which user it is. Run
75 your webserver as this user.
76 - Create a `daemon-user` if one does not already exist (you can call this user
77 whatever you want, or use an existing account). Below, you'll configure
78 the daemons to start as this user.
79 - Create a `vcs-user` if one does not already exist and you plan to set up
80 SSH. When users clone repositories, they will use a URI like
81 `vcs-user@phorge.yourcompany.com`, so common names for this user are
82 `git` or `hg`.
83
84Continue below to configure these accounts.
85
86
87Configuring Phorge
88=======================
89
90Now that you have created or identified these accounts, update the Phorge
91configuration to specify them.
92
93First, set `phd.user` to the `daemon-user`:
94
95```
96phorge/ $ ./bin/config set phd.user daemon-user
97```
98
99Restart the daemons to make sure this configuration works properly. They should
100start as the correct user automatically.
101
102If you're using a `vcs-user` for SSH, you should also configure that:
103
104```
105phorge/ $ ./bin/config set diffusion.ssh-user vcs-user
106```
107
108Next, you'll set up `sudo` permissions so these users can interact with one
109another.
110
111
112Configuring Sudo
113================
114
115The `www-user` and `vcs-user` need to be able to `sudo` as the `daemon-user`
116so they can interact with repositories.
117
118To grant them access, edit the `sudo` system configuration. On many systems,
119you will do this by modifying the `/etc/sudoers` file using `visudo` or
120`sudoedit`. In some cases, you may add a new file to `/etc/sudoers.d` instead.
121
122To give a user account `sudo` access to run a list of binaries, add a line like
123this to the configuration file (this example would grant `vcs-user` permission
124to run `ls` as `daemon-user`):
125
126```
127vcs-user ALL=(daemon-user) SETENV: NOPASSWD: /path/to/bin/ls
128```
129
130The `www-user` needs to be able to run these binaries as the `daemon-user`:
131
132 - `git` (if using Git)
133 - `git-http-backend` (if using Git)
134 - `hg` (if using Mercurial)
135 - `ssh` (if configuring clusters)
136
137If you plan to use SSH, the `vcs-user` needs to be able to run these binaries
138as the `daemon-user`:
139
140 - `git` (if using Git)
141 - `git-upload-pack` (if using Git)
142 - `git-receive-pack` (if using Git)
143 - `hg` (if using Mercurial)
144 - `svnserve` (if using Subversion)
145 - `ssh` (if configuring clusters)
146
147Identify the full paths to all of these binaries on your system and add the
148appropriate permissions to the `sudo` configuration.
149
150Normally, you'll add two lines that look something like this:
151
152```
153www-user ALL=(daemon-user) SETENV: NOPASSWD: /path/to/x, /path/to/y, ...
154vcs-user ALL=(daemon-user) SETENV: NOPASSWD: /path/to/x, /path/to/y, ...
155```
156
157This is just a template. In the real configuration file, you need to:
158
159 - Replace `www-user`, `daemon-user` and `vcs-user` with the correct
160 usernames for your system.
161 - List every binary that these users need access to, as described above.
162 - Make sure each binary path is the full path to the correct binary location
163 on your system.
164
165Before continuing, look for this line in your `sudo` configuration:
166
167 Defaults requiretty
168
169If it's present, comment it out by putting a `#` at the beginning of the line.
170With this option enabled, VCS SSH sessions won't be able to use `sudo`.
171
172
173Additional SSH User Configuration
174=================================
175
176If you're planning to use SSH, you should also edit `/etc/passwd` and
177`/etc/shadow` to make sure the `vcs-user` account is set up correctly.
178
179**`/etc/shadow`**: Open `/etc/shadow` and find the line for the `vcs-user`
180account.
181
182The second field (which is the password field) must not be set to `!!`. This
183value will prevent login.
184
185If you have `usermod` on your system, you can adjust this value with:
186
187```
188$ sudo usermod -p NP vcs-user
189```
190
191If you do not have `usermod`, carefully edit the file and set the field value
192to `NP` ("no password") instead of `!!`.
193
194**`/etc/passwd`**: Open `/etc/passwd` and find the line for the `vcs-user`
195account.
196
197The last field (which is the login shell) must be set to a real shell. If it is
198set to something like `/bin/false`, then `sshd` will not be able to execute
199commands.
200
201If you have `usermod` on your system, you can adjust this value with:
202
203```
204$ sudo usermod -s /bin/sh vcs-user
205```
206
207If you do not have `usermod`, carefully edit the file and change the field
208to point at a real shell, usually `/bin/sh`.
209
210
211Configuring HTTP
212================
213
214If you plan to serve repositories over authenticated HTTP, you need to set
215`diffusion.allow-http-auth` in Config. If you don't plan to serve repositories
216over HTTP (or plan to use only anonymous HTTP) you can leave this setting
217disabled.
218
219If you plan to use authenticated HTTP, you (and all other users) also need to
220configure a VCS password for your account in {nav Settings > VCS Password}.
221
222Your VCS password must be a different password than your main Phorge
223password because VCS passwords are very easy to accidentally disclose. They are
224often stored in plaintext in world-readable files, observable in `ps` output,
225and present in command output and logs. We strongly encourage you to use SSH
226instead of HTTP to authenticate access to repositories.
227
228Otherwise, if you've configured system accounts above, you're all set. No
229additional server configuration is required to make HTTP work. You should now
230be able to fetch and push repositories over HTTP. See "Cloning a Repository"
231below for more details.
232
233If you're having trouble, see "Troubleshooting HTTP" below.
234
235
236Configuring SSH
237===============
238
239SSH access requires some additional setup. You will configure and run a second,
240restricted copy of `sshd` on the machine, on a different port from the standard
241`sshd`. This special copy of `sshd` will serve repository requests and provide
242other Phorge SSH services.
243
244NOTE: The Phorge `sshd` service **MUST** be 6.2 or newer, because
245Phorge relies on the `AuthorizedKeysCommand` option.
246
247Before continuing, you must choose a strategy for which port each copy of
248`sshd` will run on. The next section lays out various approaches.
249
250
251SSHD Port Assignment
252====================
253
254The normal `sshd` that lets you administrate the host and the special `sshd`
255which serves repositories can't run on the same port. In particular, only one
256of them can run on port `22`, which will make it a bit inconvenient to access
257the other one.
258
259These instructions will walk you through configuring the alternate `sshd` on
260port `2222`. This is easy to configure, but if you run the service on this port
261users will clone and push to URIs like `ssh://git@host.com:2222/`, which is a
262little ugly.
263
264There are several different approaches you can use to mitigate or eliminate
265this problem.
266
267**Run on Port 2222**: You can do nothing, and just run the repository `sshd` on
268port `2222` and accept the explicit port in the URIs. This is the simplest
269approach, and you can always start here and clean things up later if you grow
270tired of dealing with the port number.
271
272**Use a Load Balancer**: You can configure a load balancer in front of the host
273and have it forward TCP traffic on port `22` to port `2222`. Then users can
274clone from `ssh://git@host.com/` without an explicit port number and you don't
275need to do anything else.
276
277This may be very easy to set up, particularly if you are hosted in AWS, and
278is often the simplest and cleanest approach.
279
280**Swap Ports**: You can move the administrative `sshd` to a new port, then run
281Phorge `sshd` on port 22. This is somewhat complicated and can be a bit
282risky if you make a mistake. See "Moving the sshd Port" below for help.
283
284**Change Client Config**: You can run on a nonstandard port, but configure SSH
285on the client side so that `ssh` automatically defaults to the correct port
286when connecting to the host. To do this, add a section like this to your
287`~/.ssh/config`:
288
289```
290Host phorge.corporation.com
291 Port 2222
292```
293
294(If you want, you can also add a default `User`.)
295
296Command line tools like `ssh`, `git` and `hg` will now default to port
297`2222` when connecting to this host.
298
299A downside to this approach is that your users will each need to set up their
300`~/.ssh/config` files individually.
301
302This file also allows you to define short names for hosts using the `Host` and
303`HostName` options. If you choose to do this, be aware that Phorge uses
304remote/clone URIs to figure out which repository it is operating in, but can
305not resolve host aliases defined in your `ssh` config. If you create host
306aliases they may break some features related to repository identification.
307
308If you use this approach, you will also need to specify a port explicitly when
309connecting to administrate the host. Any unit tests or other build automation
310will also need to be configured or use explicit port numbers.
311
312**Port Multiplexing**: If you have hardware access, you can power down the host
313and find the network I/O pins on the motherboard (for onboard networking) or
314network card.
315
316Carefully strip and solder a short piece of copper wire between the pins for
317the external interface `22` and internal `2222`, so the external interface can
318receive traffic for both services.
319
320(Make sure not to desolder the existing connection between external `22` and
321internal `22` or you won't be able to connect normally to administrate the
322host.)
323
324The obvious downside to this approach is that it requires physical access to
325the machine, so it won't work if you're hosted on a cloud provider.
326
327
328SSHD Setup
329==========
330
331Now that you've decided how you'll handle port assignment, you're ready to
332continue `sshd` setup.
333
334If you plan to connect to a port other than `22`, you should set this port
335as `diffusion.ssh-port` in your Phorge config:
336
337```
338$ ./bin/config set diffusion.ssh-port 2222
339```
340
341This port is not special, and you are free to choose a different port, provided
342you make the appropriate configuration adjustment below.
343
344**Configure and Start Phorge SSHD**: Now, you'll configure and start a
345copy of `sshd` which will serve Phorge services, including repositories,
346over SSH.
347
348This instance will use a special locked-down configuration that uses
349Phorge to handle authentication and command execution.
350
351There are three major steps:
352
353 - Create a `phorge-ssh-hook.sh` file.
354 - Create a `sshd_phorge config file.
355 - Start a copy of `sshd` using the new configuration.
356
357**Create `phorge-ssh-hook.sh`**: Copy the template in
358`phorge/resources/sshd/phorge-ssh-hook.sh` to somewhere like
359`/usr/libexec/phorge-ssh-hook.sh` and edit it to have the correct
360settings.
361
362Both the script itself **and** the parent directory the script resides in must
363be owned by `root`, and the script must have `755` permissions:
364
365```
366$ sudo chown root /path/to/somewhere/
367$ sudo chown root /path/to/somewhere/phorge-ssh-hook.sh
368$ sudo chmod 755 /path/to/somewhere/phorge-ssh-hook.sh
369```
370
371If you don't do this, `sshd` will refuse to execute the hook.
372
373**Create `sshd_config` for Phorge**: Copy the template in
374`phorge/resources/sshd/sshd_config.phorge.example` to somewhere like
375`/etc/ssh/sshd_config.phorge`.
376
377Open the file and edit the `AuthorizedKeysCommand`,
378`AuthorizedKeysCommandUser`, and `AllowUsers` settings to be correct for your
379system.
380
381This configuration file also specifies the `Port` the service should run on.
382If you intend to run on a non-default port, adjust it now.
383
384**Start SSHD**: Now, start the Phorge `sshd`:
385
386 sudo /path/to/sshd -f /path/to/sshd_config.phorge
387
388If you did everything correctly, you should be able to run this command:
389
390```
391$ echo {} | ssh vcs-user@phorge.yourcompany.com conduit conduit.ping --
392```
393
394...and get a response like this:
395
396```lang=json
397{"result":"phorge.yourcompany.com","error_code":null,"error_info":null}
398```
399
400If you get an authentication error, make sure you added your public key in
401{nav Settings > SSH Public Keys}. If you're having trouble, check the
402troubleshooting section below.
403
404Authentication Over SSH
405=======================
406
407To authenticate over SSH, users should add their public keys under
408{nav Settings > SSH Public Keys}.
409
410
411Cloning a Repository
412====================
413
414If you've already set up a hosted repository, you can try cloning it now. To
415do this, browse to the repository's main screen in Diffusion. You should see
416clone commands at the top of the page.
417
418To clone the repository, just run the appropriate command.
419
420If you don't see the commands or running them doesn't work, see below for tips
421on troubleshooting.
422
423
424Troubleshooting HTTP
425====================
426
427Some general tips for troubleshooting problems with HTTP:
428
429 - Make sure `diffusion.allow-http-auth` is enabled in your Phorge config.
430 - Make sure HTTP serving is enabled for the repository you're trying to
431 clone. You can find this in {nav Edit Repository > Hosting}.
432 - Make sure you've configured a VCS password. This is separate from your main
433 account password. You can configure this in {nav Settings > VCS Password}.
434 - Make sure the main repository screen in Diffusion shows a clone/checkout
435 command for HTTP. If it doesn't, something above isn't set up correctly:
436 double-check your configuration. You should see a `svn checkout http://...`,
437 `git clone http://...` or `hg clone http://...` command. Run that command
438 verbatim to clone the repository.
439
440If you're using Git, using `GIT_CURL_VERBOSE` may help assess login failures.
441To do so, specify it on the command line before the `git clone` command, like
442this:
443
444 $ GIT_CURL_VERBOSE=1 git clone ...
445
446This will make `git` print out a lot more information. Particularly, the line
447with the HTTP response is likely to be useful:
448
449 < HTTP/1.1 403 Invalid credentials.
450
451In many cases, this can give you more information about what's wrong.
452
453Troubleshooting SSH
454===================
455
456Some general tips for troubleshooting problems with SSH:
457
458 - Check that you've configured `diffusion.ssh-user`.
459 - Check that you've configured `phd.user`.
460 - Make sure SSH serving is enabled for the repository you're trying to clone.
461 You can change this setting from a main repository screen in Diffusion by
462 {nav Edit Repository >
463 Edit Hosting >
464 Host Repository on Phabricator >
465 Save and Continue >
466 SSH Read Only or Read/Write >
467 Save Changes}.
468 - Make sure you've added an SSH public key to your account. You can do this
469 in {nav Settings > SSH Public Keys}.
470 - Make sure the main repository screen in Diffusion shows a clone/checkout
471 command for SSH. If it doesn't, something above isn't set up correctly.
472 You should see an `svn checkout svn+ssh://...`, `git clone ssh://...` or
473 `hg clone ssh://...` command. Run that command verbatim to clone the
474 repository.
475 - Check your `phorge-ssh-hook.sh` file for proper settings.
476 - Check your `sshd_config.phorge` file for proper settings.
477
478To troubleshoot SSH setup: connect to the server with `ssh`, without running a
479command. You may need to use the `-T` flag, and will need to use `-p` if you
480are running on a nonstandard port. You should see a message like this one:
481
482 $ ssh -T -p 2222 vcs-user@phorge.yourcompany.com
483 phorge-ssh-exec: Welcome to Phorge.
484
485 You are logged in as alincoln.
486
487 You haven't specified a command to run. This means you're requesting an
488 interactive shell, but Phorge does not provide an interactive shell over
489 SSH.
490
491 Usually, you should run a command like `git clone` or `hg push` rather than
492 connecting directly with SSH.
493
494 Supported commands are: conduit, git-receive-pack, git-upload-pack, hg,
495 svnserve.
496
497If you see this message, all your SSH stuff is configured correctly. **If you
498get a login shell instead, you've missed some major setup step: review the
499documentation above.** If you get some other sort of error, double check these
500settings:
501
502 - You're connecting as the `vcs-user`.
503 - The `vcs-user` has `NP` in `/etc/shadow`.
504 - The `vcs-user` has `/bin/sh` or some other valid shell in `/etc/passwd`.
505 - Your SSH private key is correct, and you've added the corresponding
506 public key to Phorge in the Settings panel.
507
508If you can get this far, but can't execute VCS commands like `git clone`, there
509is probably an issue with your `sudoers` configuration. Check:
510
511 - Your `sudoers` file is set up as instructed above.
512 - You've commented out `Defaults requiretty` in `sudoers`.
513 - You don't have multiple copies of the VCS binaries (like `git-upload-pack`)
514 on your system. You may have granted sudo access to one, while the VCS user
515 is trying to run a different one.
516 - You've configured `phd.user`.
517 - The `phd.user` has read and write access to the repositories.
518
519It may also be helpful to run `sshd` in debug mode:
520
521 $ /path/to/sshd -d -d -d -f /path/to/sshd_config.phorge
522
523This will run it in the foreground and emit a large amount of debugging
524information when you connect to it.
525
526Finally, you can usually test that `sudoers` is configured correctly by
527doing something like this:
528
529 $ su vcs-user
530 $ sudo -E -n -u daemon-user -- /path/to/some/vcs-binary --help
531
532That will try to run the binary via `sudo` in a manner similar to the way that
533Phorge will run it. This can give you better error messages about issues
534with `sudoers` configuration.
535
536
537Miscellaneous Troubleshooting
538=============================
539
540 - If you're getting an error about `svnlook` not being found, add the path
541 where `svnlook` is located to the Phorge configuration
542 `environment.append-paths` (even if it already appears in PATH). This issue
543 is caused by SVN wiping the environment (including PATH) when invoking
544 commit hooks.
545
546
547Moving the sshd Port
548====================
549
550If you want to move the standard (administrative) `sshd` to a different port to
551make Phorge repository URIs cleaner, this section has some tips.
552
553This is optional, and it is normally easier to do this by putting a load
554balancer in front of Phorge and having it accept TCP traffic on port 22
555and forward it to some other port.
556
557When moving `sshd`, be careful when editing the configuration. If you get it
558wrong, you may lock yourself out of the machine. Restarting `sshd` generally
559will not interrupt existing connections, but you should exercise caution. Two
560strategies you can use to mitigate this risk are: smoke-test configuration by
561starting a second `sshd`; and use a `screen` session which automatically
562repairs configuration unless stopped.
563
564To smoke-test a configuration, just start another `sshd` using the `-f` flag:
565
566 sudo /path/to/sshd -f /path/to/config_file.edited
567
568You can then connect and make sure the edited config file is valid before
569replacing your primary configuration file.
570
571To automatically repair configuration, start a `screen` session with a command
572like this in it:
573
574 sleep 60 ; mv sshd_config.good sshd_config ; /etc/init.d/sshd restart
575
576The specific command may vary for your system, but the general idea is to have
577the machine automatically restore configuration after some period of time if
578you don't stop it. If you lock yourself out, this can fix things automatically.
579
580Now that you're ready to edit your configuration, open up your `sshd` config
581(often `/etc/ssh/sshd_config`) and change the `Port` setting to some other port,
582like `222` (you can choose any port other than 22).
583
584 Port 222
585
586Very carefully, restart `sshd`. Verify that you can connect on the new port:
587
588 ssh -p 222 ...
589
590Now you can move the Phorge `sshd` to port 22, then adjust the value
591for `diffusion.ssh-port` in your Phorge configuration.
592
593You can set up and enable this systemd unit to start the second sshd
594daemon on every reboot:
595
596```
597name=/etc/systemd/system/phorge-ssh.service,lang=ini
598[Unit]
599Description=Phorge sshd
600Documentation=https://we.phorge.it/book/phorge/article/diffusion_hosting/#sshd-setup
601After=network.target auditd.service
602
603[Service]
604ExecStartPre=/usr/sbin/sshd -t -f /path/to/config_file.edited
605ExecStart=/usr/sbin/sshd -f /path/to/config_file.edited
606ExecReload=/usr/sbin/sshd -t -f /path/to/config_file.edited
607ExecReload=/bin/kill -HUP $MAINPID
608KillMode=process
609Restart=on-failure
610RestartPreventExitStatus=255
611Type=notify
612RuntimeDirectory=sshd
613RuntimeDirectoryMode=0755
614
615[Install]
616WantedBy=multi-user.target
617Alias=phorge-sshd.service
618```
619
620No Direct Pushes
621================
622
623You may get an error about "No Direct Pushes" when trying to push. This means
624you are pushing directly to the repository instead of pushing through
625Phorge. This is not supported: writes to hosted repositories must go
626through Phorge so it can perform authentication, enforce permissions,
627write logs, proxy requests, apply rewriting, etc.
628
629One way to do a direct push by mistake is to use a `file:///` URI to interact
630with the repository from the same machine. This is not supported. Instead, use
631one of the repository URIs provided in the web interface, even if you're
632working on the same machine.
633
634Another way to do a direct push is to misconfigure SSH (or not configure it at
635all) so that none of the logic described above runs and you just connect
636normally as a system user. In this case, the `ssh` test described above will
637fail (you'll get a command prompt when you connect, instead of the message you
638are supposed to get, as described above).
639
640If you encounter this error: make sure you're using a remote URI given to
641you by Diffusion in the web interface, then run through the troubleshooting
642steps above carefully.
643
644Sometimes users encounter this problem because they skip this whole document
645assuming they don't need to configure anything. This will not work, and you
646MUST configure things as described above for hosted repositories to work.
647
648The technical reason this error occurs is that the `PHABRICATOR_USER` variable
649is not defined in the environment when commit hooks run. This variable is set
650by Phorge when a request passes through the authentication layer that this
651document provides instructions for configuring. Its absence indicates that the
652request did not pass through Phorge.
653
654
655Next Steps
656==========
657
658Once hosted repositories are set up:
659
660 - learn about commit hooks with @{article:Diffusion User Guide: Commit Hooks}.