Fossil SCM
OpenBSD server docs: Add instructions to make fossil.log owned by 'www' user, and repository directory group writeable; remove unnecessary 'directory index' option in httpd.conf; and fix redundant double backticks.
Commit
8ce8828d0c1d38d518c6857267023040c63853a5bcd958c48073aceb633058ae
Parent
02a7c72bf97276c…
1 file changed
+68
-65
+68
-65
| --- www/server/openbsd/httpd.md | ||
| +++ www/server/openbsd/httpd.md | ||
| @@ -4,22 +4,22 @@ | ||
| 4 | 4 | install on OpenBSD. It's minimal and lightweight but secure and capable, |
| 5 | 5 | and provides a clean interface for setting up a Fossil server using |
| 6 | 6 | FastCGI. |
| 7 | 7 | |
| 8 | 8 | This article will detail the steps required to setup a TLS-enabled |
| 9 | -``httpd`` configuration that serves multiple Fossil repositories out of | |
| 10 | -a single directory within a chroot, and allow ``ssh`` access to create | |
| 9 | +`httpd` configuration that serves multiple Fossil repositories out of | |
| 10 | +a single directory within a chroot, and allow `ssh` access to create | |
| 11 | 11 | new repositories remotely. |
| 12 | 12 | |
| 13 | 13 | **NOTE:** The following instructions assume an OpenBSD 6.7 installation. |
| 14 | 14 | |
| 15 | 15 | [httpd]: https://www.openbsd.org/papers/httpd-asiabsdcon2015.pdf |
| 16 | 16 | |
| 17 | 17 | ## <a name="fslinstall"></a>Install Fossil |
| 18 | 18 | |
| 19 | -Use the OpenBSD package manager ``pkg_add`` to install Fossil, making | |
| 20 | -sure to select the statically linked binary. | |
| 19 | +Use the OpenBSD package manager `pkg_add` to install Fossil, making sure | |
| 20 | +to select the statically linked binary. | |
| 21 | 21 | |
| 22 | 22 | ```console |
| 23 | 23 | $ doas pkg_add fossil |
| 24 | 24 | quirks-3.325 signed on 2020-06-12T06:24:53Z |
| 25 | 25 | Ambiguous: choose package for fossil |
| @@ -29,48 +29,50 @@ | ||
| 29 | 29 | Your choice: 2 |
| 30 | 30 | fossil-2.10v0-static: ok |
| 31 | 31 | ``` |
| 32 | 32 | |
| 33 | 33 | This installs Fossil into the chroot. To facilitate local use, create a |
| 34 | -symbolic link of the fossil executable into ``/usr/local/bin``. | |
| 34 | +symbolic link of the fossil executable into `/usr/local/bin`. | |
| 35 | 35 | |
| 36 | 36 | ```console |
| 37 | 37 | $ doas ln -s /var/www/bin/fossil /usr/local/bin/fossil |
| 38 | 38 | ``` |
| 39 | 39 | |
| 40 | -As a privileged user, create the file ``/var/www/cgi-bin/scm`` with the | |
| 41 | -following contents to make the CGI script that ``httpd`` will execute in | |
| 42 | -response to ``fsl.domain.tld`` requests; all paths are relative to the | |
| 43 | -``/var/www`` chroot. | |
| 40 | +As a privileged user, create the file `/var/www/cgi-bin/scm` with the | |
| 41 | +following contents to make the CGI script that `httpd` will execute in | |
| 42 | +response to `fsl.domain.tld` requests; all paths are relative to the | |
| 43 | +`/var/www` chroot. | |
| 44 | 44 | |
| 45 | 45 | ```sh |
| 46 | 46 | #!/bin/fossil |
| 47 | 47 | directory: /htdocs/fsl.domain.tld |
| 48 | 48 | notfound: https://domain.tld |
| 49 | 49 | repolist |
| 50 | 50 | errorlog: /logs/fossil.log |
| 51 | 51 | ``` |
| 52 | 52 | |
| 53 | -The ``directory`` directive instructs Fossil to serve all repositories | |
| 54 | -found in ``/var/www/htdocs/fsl.domain.tld``, while ``errorlog`` sets | |
| 55 | -logging to be saved to ``/var/www/logs/fossil.log``; create the | |
| 56 | -repository directory and log file, and make the script executable. | |
| 53 | +The `directory` directive instructs Fossil to serve all repositories | |
| 54 | +found in `/var/www/htdocs/fsl.domain.tld`, while `errorlog` sets logging | |
| 55 | +to be saved to `/var/www/logs/fossil.log`; create the repository | |
| 56 | +directory and log file—making the latter owned by the `www` user, and | |
| 57 | +the script executable. | |
| 57 | 58 | |
| 58 | 59 | ```console |
| 59 | 60 | $ doas mkdir /var/www/htdocs/fsl.domain.tld |
| 60 | 61 | $ doas touch /var/www/logs/fossil.log |
| 62 | + $ doas chown www /var/www/logs/fossil.log | |
| 61 | 63 | $ doas chmod 755 /var/www/cgi-bin/scm |
| 62 | 64 | ``` |
| 63 | 65 | |
| 64 | 66 | ## <a name="chroot"></a>Setup chroot |
| 65 | 67 | |
| 66 | -Fossil needs both ``/dev/random`` and ``/dev/null``, which aren't | |
| 67 | -accessible from within the chroot, so need to be constructed; ``/var``, | |
| 68 | -however, is mounted with the ``nodev`` option. Rather than removing | |
| 69 | -this default setting, create a small memory filesystem with | |
| 70 | -[`mount_mfs(8)`][mfs] upon which ``/var/www/dev`` will be mounted so | |
| 71 | -that the ``random`` and ``null`` device files can be created. | |
| 68 | +Fossil needs both `/dev/random` and `/dev/null`, which aren't accessible | |
| 69 | +from within the chroot, so need to be constructed; `/var`, however, is | |
| 70 | +mounted with the `nodev` option. Rather than removing this default | |
| 71 | +setting, create a small memory filesystem with [`mount_mfs(8)`][mfs] | |
| 72 | +upon which `/var/www/dev` will be mounted so that the `random` and | |
| 73 | +`null` device files can be created. | |
| 72 | 74 | |
| 73 | 75 | ```console |
| 74 | 76 | $ doas mkdir /var/www/dev |
| 75 | 77 | $ doas mount_mfs -s 1M /dev/sd0b /var/www/dev |
| 76 | 78 | $ doas cd /var/www/dev |
| @@ -83,35 +85,36 @@ | ||
| 83 | 85 | crw-r--r-- 1 root wheel 45, 0 Jun 18 06:30 urandom |
| 84 | 86 | ``` |
| 85 | 87 | |
| 86 | 88 | [mfs]: https://man.openbsd.org/mount_mfs.8 |
| 87 | 89 | |
| 88 | -To make the mountable memory filesystem permanent, open ``/etc/fstab`` | |
| 89 | -as a privileged user and add the following line to automate creation of | |
| 90 | -the filesystem at startup: | |
| 90 | +To make the mountable memory filesystem permanent, open `/etc/fstab` as | |
| 91 | +a privileged user and add the following line to automate creation of the | |
| 92 | +filesystem at startup: | |
| 91 | 93 | |
| 92 | 94 | ```console |
| 93 | 95 | swap /var/www/dev mfs rw,-s=1048576 0 0 |
| 94 | 96 | ``` |
| 95 | 97 | |
| 96 | 98 | The same user that executes the fossil binary must have writable access |
| 97 | 99 | to the repository directory that resides within the chroot; on OpenBSD |
| 98 | -this is ``www``. In addition, grant repository directory ownership to | |
| 99 | -the user who will push to, pull from, and create repositories. | |
| 100 | +this is `www`. In addition, grant repository directory ownership to the | |
| 101 | +user who will push to, pull from, and create repositories. | |
| 100 | 102 | |
| 101 | 103 | ```console |
| 102 | 104 | $ doas chown -R user:www /var/www/htdocs/fsl.domain.tld |
| 105 | + $ doas chmod 775 /var/www/htdocs/fsl.domain.tld | |
| 103 | 106 | ``` |
| 104 | 107 | |
| 105 | 108 | ## <a name="httpdconfig"></a>Configure httpd |
| 106 | 109 | |
| 107 | 110 | On OpenBSD, [httpd.conf(5)][httpd] is the configuration file for |
| 108 | -``httpd``. To setup the server to serve all Fossil repositores within | |
| 109 | -the directory specified in the CGI script, and automatically redirect | |
| 111 | +`httpd`. To setup the server to serve all Fossil repositores within the | |
| 112 | +directory specified in the CGI script, and automatically redirect | |
| 110 | 113 | standard HTTP requests to HTTPS—apart from [Let's Encrypt][LE] |
| 111 | 114 | challenges issued in response to [acme-client(1)][acme] certificate |
| 112 | -requests—create ``/etc/httpd.conf`` as a privileged user with the | |
| 115 | +requests—create `/etc/httpd.conf` as a privileged user with the | |
| 113 | 116 | following contents. |
| 114 | 117 | |
| 115 | 118 | [LE]: https://letsencrypt.org |
| 116 | 119 | [acme]: https://man.openbsd.org/acme-client.1 |
| 117 | 120 | [httpd.conf(5)]: https://man.openbsd.org/httpd.conf.5 |
| @@ -143,11 +146,10 @@ | ||
| 143 | 146 | max-age 15768000 |
| 144 | 147 | preload |
| 145 | 148 | subdomains |
| 146 | 149 | } |
| 147 | 150 | connection max request body 104857600 |
| 148 | - directory index "index.cgi" | |
| 149 | 151 | location "/*" { |
| 150 | 152 | fastcgi { param SCRIPT_FILENAME "/cgi-bin/scm" } |
| 151 | 153 | } |
| 152 | 154 | location "/.well-known/acme-challenge/*" { |
| 153 | 155 | root "/acme" |
| @@ -155,21 +157,21 @@ | ||
| 155 | 157 | } |
| 156 | 158 | } |
| 157 | 159 | ``` |
| 158 | 160 | |
| 159 | 161 | **NOTE:** If not already in possession of a HTTPS certificate, comment |
| 160 | -out the ``https`` server block and proceed to securing a free | |
| 162 | +out the `https` server block and proceed to securing a free | |
| 161 | 163 | [Let's Encrypt Certificate](#letsencrypt); otherwise skip to |
| 162 | -[Start httpd](#starthttpd). | |
| 164 | +[Start `httpd`](#starthttpd). | |
| 163 | 165 | |
| 164 | 166 | ## <a name="letsencrypt"></a>Let's Encrypt Certificate |
| 165 | 167 | |
| 166 | -In order for ``httpd`` to serve HTTPS, secure a free certificate from | |
| 167 | -Let's Encrypt using ``acme-client``. Before issuing the | |
| 168 | -request, however, ensure you have a zone record for the subdomain with | |
| 169 | -your registrar or nameserver. Then open ``/etc/acme-client.conf`` as a | |
| 170 | -privileged user to configure the request. | |
| 168 | +In order for `httpd` to serve HTTPS, secure a free certificate from | |
| 169 | +Let's Encrypt using `acme-client`. Before issuing the request, however, | |
| 170 | +ensure you have a zone record for the subdomain with your registrar or | |
| 171 | +nameserver. Then open `/etc/acme-client.conf` as a privileged user to | |
| 172 | +configure the request. | |
| 171 | 173 | |
| 172 | 174 | ```dosini |
| 173 | 175 | authority letsencrypt { |
| 174 | 176 | api url "https://acme-v02.api.letsencrypt.org/directory" |
| 175 | 177 | account key "/etc/acme/letsencrypt-privkey.pem" |
| @@ -187,13 +189,15 @@ | ||
| 187 | 189 | domain full chain certificate "/etc/ssl/domain.tld.fullchain.pem" |
| 188 | 190 | sign with letsencrypt |
| 189 | 191 | } |
| 190 | 192 | ``` |
| 191 | 193 | |
| 192 | -Issue the certificate request. | |
| 194 | +Start `httpd` with the new configuration file, and issue the certificate | |
| 195 | +request. | |
| 193 | 196 | |
| 194 | 197 | ```console |
| 198 | + $ doas rcctl start httpd | |
| 195 | 199 | $ doas acme-client -vv domain.tld |
| 196 | 200 | acme-client: /etc/acme/letsencrypt-privkey.pem: account key exists (not creating) |
| 197 | 201 | acme-client: /etc/acme/letsencrypt-privkey.pem: loaded RSA account key |
| 198 | 202 | acme-client: /etc/ssl/private/domain.tld.key: generated RSA domain key |
| 199 | 203 | acme-client: https://acme-v01.api.letsencrypt.org/directory: directories |
| @@ -203,12 +207,12 @@ | ||
| 203 | 207 | acme-client: /etc/ssl/domain.tld.crt: created |
| 204 | 208 | acme-client: /etc/ssl/domain.tld.fullchain.pem: created |
| 205 | 209 | ``` |
| 206 | 210 | |
| 207 | 211 | A successful result will output the public certificate, full chain of |
| 208 | -trust, and private key into the ``/etc/ssl`` directory as specified in | |
| 209 | -``acme-client.conf``. | |
| 212 | +trust, and private key into the `/etc/ssl` directory as specified in | |
| 213 | +`acme-client.conf`. | |
| 210 | 214 | |
| 211 | 215 | ```console |
| 212 | 216 | $ doas ls -lR /etc/ssl |
| 213 | 217 | -r--r--r-- 1 root wheel 2.3K Mar 2 01:31:03 2018 domain.tld.crt |
| 214 | 218 | -r--r--r-- 1 root wheel 3.9K Mar 2 01:31:03 2018 domain.tld.fullchain.pem |
| @@ -215,21 +219,21 @@ | ||
| 215 | 219 | |
| 216 | 220 | /etc/ssl/private: |
| 217 | 221 | -r-------- 1 root wheel 3.2K Mar 2 01:31:03 2018 domain.tld.key |
| 218 | 222 | ``` |
| 219 | 223 | |
| 220 | -Make sure to reopen ``/etc/httpd.conf`` to uncomment the second server | |
| 224 | +Make sure to reopen `/etc/httpd.conf` to uncomment the second server | |
| 221 | 225 | block responsible for serving HTTPS requests before proceeding. |
| 222 | 226 | |
| 223 | -## <a name="starthttpd"></a>Start httpd | |
| 224 | - | |
| 225 | -With ``httpd`` configured to serve Fossil repositories out of | |
| 226 | -``/var/www/htdocs/fsl.domain.tld``, and the certificates and key in | |
| 227 | -place, enable and start ``slowcgi``—OpenBSD's FastCGI wrapper server | |
| 228 | -that will execute the above Fossil CGI script—before checking the syntax | |
| 229 | -of the ``httpd.conf`` configuration file is correct, and starting the | |
| 230 | -server. | |
| 227 | +## <a name="starthttpd"></a>Start `httpd` | |
| 228 | + | |
| 229 | +With `httpd` configured to serve Fossil repositories out of | |
| 230 | +`/var/www/htdocs/fsl.domain.tld`, and the certificates and key in place, | |
| 231 | +enable and start `slowcgi`—OpenBSD's FastCGI wrapper server that will | |
| 232 | +execute the above Fossil CGI script—before checking that the syntax of | |
| 233 | +the `httpd.conf` configuration file is correct, and (re)starting the | |
| 234 | +server (if still running from requesting a Let's Encrypt certificate). | |
| 231 | 235 | |
| 232 | 236 | ```console |
| 233 | 237 | $ doas rcctl enable slowcgi |
| 234 | 238 | $ doas rcctl start slowcgi |
| 235 | 239 | slowcgi(ok) |
| @@ -240,13 +244,12 @@ | ||
| 240 | 244 | ``` |
| 241 | 245 | |
| 242 | 246 | ## <a name="clientconfig"></a>Configure Client |
| 243 | 247 | |
| 244 | 248 | To facilitate creating new repositories and pushing them to the server, |
| 245 | -add the following function to your ``~/.cshrc`` or ``~/.zprofile`` or | |
| 246 | -the config file for whichever shell you are using on your development | |
| 247 | -box. | |
| 249 | +add the following function to your `~/.cshrc` or `~/.zprofile` or the | |
| 250 | +config file for whichever shell you are using on your development box. | |
| 248 | 251 | |
| 249 | 252 | ```sh |
| 250 | 253 | finit() { |
| 251 | 254 | fossil init $1.fossil && \ |
| 252 | 255 | chmod 664 $1.fossil && \ |
| @@ -257,26 +260,26 @@ | ||
| 257 | 260 | chmod 644 $1.fossil && \ |
| 258 | 261 | fossil ui |
| 259 | 262 | } |
| 260 | 263 | ``` |
| 261 | 264 | |
| 262 | -This enables a new repository to be made with ``finit repo``, which will | |
| 263 | -create the fossil repository file ``repo.fossil`` in the current working | |
| 265 | +This enables a new repository to be made with `finit repo`, which will | |
| 266 | +create the fossil repository file `repo.fossil` in the current working | |
| 264 | 267 | directory; by default, the repository user is set to the environment |
| 265 | -variable ``$USER``. It then opens the repository and sets the user | |
| 266 | -password to the ``$PASSWD`` environment variable (which you can either | |
| 267 | -set with ``export PASSWD 'password'`` on the command line or add to a | |
| 268 | -*secured* shell environment file), and the ``remote-url`` to | |
| 269 | -https://fsl.domain.tld/repo with the credentials of ``$USER`` who is | |
| 270 | -authenticated with ``$PASSWD``. Finally, it ``rsync``'s the file to the | |
| 271 | -server before opening the local repository in your browser where you | |
| 272 | -can adjust settings such as anonymous user access, and set pertinent | |
| 273 | -repository details. Thereafter, you can add files with ``fossil add``, | |
| 274 | -and commit with ``fossil ci -m 'commit message'`` where Fossil, by | |
| 275 | -default, will push to the ``remote-url``. It's suggested you read | |
| 276 | -the [Fossil documentation][documentation]; with a sane and consistent | |
| 268 | +variable `$USER`. It then opens the repository and sets the user | |
| 269 | +password to the `$PASSWD` environment variable (which you can either set | |
| 270 | +with `export PASSWD 'password'` on the command line or add to a | |
| 271 | +*secured* shell environment file), and the `remote-url` to | |
| 272 | +`https://fsl.domain.tld/repo` with the credentials of `$USER` who is | |
| 273 | +authenticated with `$PASSWD`. Finally, it `rsync`'s the file to the | |
| 274 | +server before opening the local repository in your browser where you can | |
| 275 | +adjust settings such as anonymous user access, and set pertinent | |
| 276 | +repository details. Thereafter, you can add files with `fossil add`, and | |
| 277 | +commit with `fossil ci -m 'commit message'` where Fossil, by default, | |
| 278 | +will push to the `remote-url`. It's suggested you read the | |
| 279 | +[Fossil documentation][documentation]; with a sane and consistent | |
| 277 | 280 | development model, the system is much more efficient and cohesive than |
| 278 | -``git``—so the learning curve is not steep at all. | |
| 281 | +`git`—so the learning curve is not steep at all. | |
| 279 | 282 | |
| 280 | 283 | [documentation]: https://fossil-scm.org/home/doc/trunk/www/permutedindex.html |
| 281 | 284 | |
| 282 | 285 | *[Return to the top-level Fossil server article.](../)* |
| 283 | 286 |
| --- www/server/openbsd/httpd.md | |
| +++ www/server/openbsd/httpd.md | |
| @@ -4,22 +4,22 @@ | |
| 4 | install on OpenBSD. It's minimal and lightweight but secure and capable, |
| 5 | and provides a clean interface for setting up a Fossil server using |
| 6 | FastCGI. |
| 7 | |
| 8 | This article will detail the steps required to setup a TLS-enabled |
| 9 | ``httpd`` configuration that serves multiple Fossil repositories out of |
| 10 | a single directory within a chroot, and allow ``ssh`` access to create |
| 11 | new repositories remotely. |
| 12 | |
| 13 | **NOTE:** The following instructions assume an OpenBSD 6.7 installation. |
| 14 | |
| 15 | [httpd]: https://www.openbsd.org/papers/httpd-asiabsdcon2015.pdf |
| 16 | |
| 17 | ## <a name="fslinstall"></a>Install Fossil |
| 18 | |
| 19 | Use the OpenBSD package manager ``pkg_add`` to install Fossil, making |
| 20 | sure to select the statically linked binary. |
| 21 | |
| 22 | ```console |
| 23 | $ doas pkg_add fossil |
| 24 | quirks-3.325 signed on 2020-06-12T06:24:53Z |
| 25 | Ambiguous: choose package for fossil |
| @@ -29,48 +29,50 @@ | |
| 29 | Your choice: 2 |
| 30 | fossil-2.10v0-static: ok |
| 31 | ``` |
| 32 | |
| 33 | This installs Fossil into the chroot. To facilitate local use, create a |
| 34 | symbolic link of the fossil executable into ``/usr/local/bin``. |
| 35 | |
| 36 | ```console |
| 37 | $ doas ln -s /var/www/bin/fossil /usr/local/bin/fossil |
| 38 | ``` |
| 39 | |
| 40 | As a privileged user, create the file ``/var/www/cgi-bin/scm`` with the |
| 41 | following contents to make the CGI script that ``httpd`` will execute in |
| 42 | response to ``fsl.domain.tld`` requests; all paths are relative to the |
| 43 | ``/var/www`` chroot. |
| 44 | |
| 45 | ```sh |
| 46 | #!/bin/fossil |
| 47 | directory: /htdocs/fsl.domain.tld |
| 48 | notfound: https://domain.tld |
| 49 | repolist |
| 50 | errorlog: /logs/fossil.log |
| 51 | ``` |
| 52 | |
| 53 | The ``directory`` directive instructs Fossil to serve all repositories |
| 54 | found in ``/var/www/htdocs/fsl.domain.tld``, while ``errorlog`` sets |
| 55 | logging to be saved to ``/var/www/logs/fossil.log``; create the |
| 56 | repository directory and log file, and make the script executable. |
| 57 | |
| 58 | ```console |
| 59 | $ doas mkdir /var/www/htdocs/fsl.domain.tld |
| 60 | $ doas touch /var/www/logs/fossil.log |
| 61 | $ doas chmod 755 /var/www/cgi-bin/scm |
| 62 | ``` |
| 63 | |
| 64 | ## <a name="chroot"></a>Setup chroot |
| 65 | |
| 66 | Fossil needs both ``/dev/random`` and ``/dev/null``, which aren't |
| 67 | accessible from within the chroot, so need to be constructed; ``/var``, |
| 68 | however, is mounted with the ``nodev`` option. Rather than removing |
| 69 | this default setting, create a small memory filesystem with |
| 70 | [`mount_mfs(8)`][mfs] upon which ``/var/www/dev`` will be mounted so |
| 71 | that the ``random`` and ``null`` device files can be created. |
| 72 | |
| 73 | ```console |
| 74 | $ doas mkdir /var/www/dev |
| 75 | $ doas mount_mfs -s 1M /dev/sd0b /var/www/dev |
| 76 | $ doas cd /var/www/dev |
| @@ -83,35 +85,36 @@ | |
| 83 | crw-r--r-- 1 root wheel 45, 0 Jun 18 06:30 urandom |
| 84 | ``` |
| 85 | |
| 86 | [mfs]: https://man.openbsd.org/mount_mfs.8 |
| 87 | |
| 88 | To make the mountable memory filesystem permanent, open ``/etc/fstab`` |
| 89 | as a privileged user and add the following line to automate creation of |
| 90 | the filesystem at startup: |
| 91 | |
| 92 | ```console |
| 93 | swap /var/www/dev mfs rw,-s=1048576 0 0 |
| 94 | ``` |
| 95 | |
| 96 | The same user that executes the fossil binary must have writable access |
| 97 | to the repository directory that resides within the chroot; on OpenBSD |
| 98 | this is ``www``. In addition, grant repository directory ownership to |
| 99 | the user who will push to, pull from, and create repositories. |
| 100 | |
| 101 | ```console |
| 102 | $ doas chown -R user:www /var/www/htdocs/fsl.domain.tld |
| 103 | ``` |
| 104 | |
| 105 | ## <a name="httpdconfig"></a>Configure httpd |
| 106 | |
| 107 | On OpenBSD, [httpd.conf(5)][httpd] is the configuration file for |
| 108 | ``httpd``. To setup the server to serve all Fossil repositores within |
| 109 | the directory specified in the CGI script, and automatically redirect |
| 110 | standard HTTP requests to HTTPS—apart from [Let's Encrypt][LE] |
| 111 | challenges issued in response to [acme-client(1)][acme] certificate |
| 112 | requests—create ``/etc/httpd.conf`` as a privileged user with the |
| 113 | following contents. |
| 114 | |
| 115 | [LE]: https://letsencrypt.org |
| 116 | [acme]: https://man.openbsd.org/acme-client.1 |
| 117 | [httpd.conf(5)]: https://man.openbsd.org/httpd.conf.5 |
| @@ -143,11 +146,10 @@ | |
| 143 | max-age 15768000 |
| 144 | preload |
| 145 | subdomains |
| 146 | } |
| 147 | connection max request body 104857600 |
| 148 | directory index "index.cgi" |
| 149 | location "/*" { |
| 150 | fastcgi { param SCRIPT_FILENAME "/cgi-bin/scm" } |
| 151 | } |
| 152 | location "/.well-known/acme-challenge/*" { |
| 153 | root "/acme" |
| @@ -155,21 +157,21 @@ | |
| 155 | } |
| 156 | } |
| 157 | ``` |
| 158 | |
| 159 | **NOTE:** If not already in possession of a HTTPS certificate, comment |
| 160 | out the ``https`` server block and proceed to securing a free |
| 161 | [Let's Encrypt Certificate](#letsencrypt); otherwise skip to |
| 162 | [Start httpd](#starthttpd). |
| 163 | |
| 164 | ## <a name="letsencrypt"></a>Let's Encrypt Certificate |
| 165 | |
| 166 | In order for ``httpd`` to serve HTTPS, secure a free certificate from |
| 167 | Let's Encrypt using ``acme-client``. Before issuing the |
| 168 | request, however, ensure you have a zone record for the subdomain with |
| 169 | your registrar or nameserver. Then open ``/etc/acme-client.conf`` as a |
| 170 | privileged user to configure the request. |
| 171 | |
| 172 | ```dosini |
| 173 | authority letsencrypt { |
| 174 | api url "https://acme-v02.api.letsencrypt.org/directory" |
| 175 | account key "/etc/acme/letsencrypt-privkey.pem" |
| @@ -187,13 +189,15 @@ | |
| 187 | domain full chain certificate "/etc/ssl/domain.tld.fullchain.pem" |
| 188 | sign with letsencrypt |
| 189 | } |
| 190 | ``` |
| 191 | |
| 192 | Issue the certificate request. |
| 193 | |
| 194 | ```console |
| 195 | $ doas acme-client -vv domain.tld |
| 196 | acme-client: /etc/acme/letsencrypt-privkey.pem: account key exists (not creating) |
| 197 | acme-client: /etc/acme/letsencrypt-privkey.pem: loaded RSA account key |
| 198 | acme-client: /etc/ssl/private/domain.tld.key: generated RSA domain key |
| 199 | acme-client: https://acme-v01.api.letsencrypt.org/directory: directories |
| @@ -203,12 +207,12 @@ | |
| 203 | acme-client: /etc/ssl/domain.tld.crt: created |
| 204 | acme-client: /etc/ssl/domain.tld.fullchain.pem: created |
| 205 | ``` |
| 206 | |
| 207 | A successful result will output the public certificate, full chain of |
| 208 | trust, and private key into the ``/etc/ssl`` directory as specified in |
| 209 | ``acme-client.conf``. |
| 210 | |
| 211 | ```console |
| 212 | $ doas ls -lR /etc/ssl |
| 213 | -r--r--r-- 1 root wheel 2.3K Mar 2 01:31:03 2018 domain.tld.crt |
| 214 | -r--r--r-- 1 root wheel 3.9K Mar 2 01:31:03 2018 domain.tld.fullchain.pem |
| @@ -215,21 +219,21 @@ | |
| 215 | |
| 216 | /etc/ssl/private: |
| 217 | -r-------- 1 root wheel 3.2K Mar 2 01:31:03 2018 domain.tld.key |
| 218 | ``` |
| 219 | |
| 220 | Make sure to reopen ``/etc/httpd.conf`` to uncomment the second server |
| 221 | block responsible for serving HTTPS requests before proceeding. |
| 222 | |
| 223 | ## <a name="starthttpd"></a>Start httpd |
| 224 | |
| 225 | With ``httpd`` configured to serve Fossil repositories out of |
| 226 | ``/var/www/htdocs/fsl.domain.tld``, and the certificates and key in |
| 227 | place, enable and start ``slowcgi``—OpenBSD's FastCGI wrapper server |
| 228 | that will execute the above Fossil CGI script—before checking the syntax |
| 229 | of the ``httpd.conf`` configuration file is correct, and starting the |
| 230 | server. |
| 231 | |
| 232 | ```console |
| 233 | $ doas rcctl enable slowcgi |
| 234 | $ doas rcctl start slowcgi |
| 235 | slowcgi(ok) |
| @@ -240,13 +244,12 @@ | |
| 240 | ``` |
| 241 | |
| 242 | ## <a name="clientconfig"></a>Configure Client |
| 243 | |
| 244 | To facilitate creating new repositories and pushing them to the server, |
| 245 | add the following function to your ``~/.cshrc`` or ``~/.zprofile`` or |
| 246 | the config file for whichever shell you are using on your development |
| 247 | box. |
| 248 | |
| 249 | ```sh |
| 250 | finit() { |
| 251 | fossil init $1.fossil && \ |
| 252 | chmod 664 $1.fossil && \ |
| @@ -257,26 +260,26 @@ | |
| 257 | chmod 644 $1.fossil && \ |
| 258 | fossil ui |
| 259 | } |
| 260 | ``` |
| 261 | |
| 262 | This enables a new repository to be made with ``finit repo``, which will |
| 263 | create the fossil repository file ``repo.fossil`` in the current working |
| 264 | directory; by default, the repository user is set to the environment |
| 265 | variable ``$USER``. It then opens the repository and sets the user |
| 266 | password to the ``$PASSWD`` environment variable (which you can either |
| 267 | set with ``export PASSWD 'password'`` on the command line or add to a |
| 268 | *secured* shell environment file), and the ``remote-url`` to |
| 269 | https://fsl.domain.tld/repo with the credentials of ``$USER`` who is |
| 270 | authenticated with ``$PASSWD``. Finally, it ``rsync``'s the file to the |
| 271 | server before opening the local repository in your browser where you |
| 272 | can adjust settings such as anonymous user access, and set pertinent |
| 273 | repository details. Thereafter, you can add files with ``fossil add``, |
| 274 | and commit with ``fossil ci -m 'commit message'`` where Fossil, by |
| 275 | default, will push to the ``remote-url``. It's suggested you read |
| 276 | the [Fossil documentation][documentation]; with a sane and consistent |
| 277 | development model, the system is much more efficient and cohesive than |
| 278 | ``git``—so the learning curve is not steep at all. |
| 279 | |
| 280 | [documentation]: https://fossil-scm.org/home/doc/trunk/www/permutedindex.html |
| 281 | |
| 282 | *[Return to the top-level Fossil server article.](../)* |
| 283 |
| --- www/server/openbsd/httpd.md | |
| +++ www/server/openbsd/httpd.md | |
| @@ -4,22 +4,22 @@ | |
| 4 | install on OpenBSD. It's minimal and lightweight but secure and capable, |
| 5 | and provides a clean interface for setting up a Fossil server using |
| 6 | FastCGI. |
| 7 | |
| 8 | This article will detail the steps required to setup a TLS-enabled |
| 9 | `httpd` configuration that serves multiple Fossil repositories out of |
| 10 | a single directory within a chroot, and allow `ssh` access to create |
| 11 | new repositories remotely. |
| 12 | |
| 13 | **NOTE:** The following instructions assume an OpenBSD 6.7 installation. |
| 14 | |
| 15 | [httpd]: https://www.openbsd.org/papers/httpd-asiabsdcon2015.pdf |
| 16 | |
| 17 | ## <a name="fslinstall"></a>Install Fossil |
| 18 | |
| 19 | Use the OpenBSD package manager `pkg_add` to install Fossil, making sure |
| 20 | to select the statically linked binary. |
| 21 | |
| 22 | ```console |
| 23 | $ doas pkg_add fossil |
| 24 | quirks-3.325 signed on 2020-06-12T06:24:53Z |
| 25 | Ambiguous: choose package for fossil |
| @@ -29,48 +29,50 @@ | |
| 29 | Your choice: 2 |
| 30 | fossil-2.10v0-static: ok |
| 31 | ``` |
| 32 | |
| 33 | This installs Fossil into the chroot. To facilitate local use, create a |
| 34 | symbolic link of the fossil executable into `/usr/local/bin`. |
| 35 | |
| 36 | ```console |
| 37 | $ doas ln -s /var/www/bin/fossil /usr/local/bin/fossil |
| 38 | ``` |
| 39 | |
| 40 | As a privileged user, create the file `/var/www/cgi-bin/scm` with the |
| 41 | following contents to make the CGI script that `httpd` will execute in |
| 42 | response to `fsl.domain.tld` requests; all paths are relative to the |
| 43 | `/var/www` chroot. |
| 44 | |
| 45 | ```sh |
| 46 | #!/bin/fossil |
| 47 | directory: /htdocs/fsl.domain.tld |
| 48 | notfound: https://domain.tld |
| 49 | repolist |
| 50 | errorlog: /logs/fossil.log |
| 51 | ``` |
| 52 | |
| 53 | The `directory` directive instructs Fossil to serve all repositories |
| 54 | found in `/var/www/htdocs/fsl.domain.tld`, while `errorlog` sets logging |
| 55 | to be saved to `/var/www/logs/fossil.log`; create the repository |
| 56 | directory and log file—making the latter owned by the `www` user, and |
| 57 | the script executable. |
| 58 | |
| 59 | ```console |
| 60 | $ doas mkdir /var/www/htdocs/fsl.domain.tld |
| 61 | $ doas touch /var/www/logs/fossil.log |
| 62 | $ doas chown www /var/www/logs/fossil.log |
| 63 | $ doas chmod 755 /var/www/cgi-bin/scm |
| 64 | ``` |
| 65 | |
| 66 | ## <a name="chroot"></a>Setup chroot |
| 67 | |
| 68 | Fossil needs both `/dev/random` and `/dev/null`, which aren't accessible |
| 69 | from within the chroot, so need to be constructed; `/var`, however, is |
| 70 | mounted with the `nodev` option. Rather than removing this default |
| 71 | setting, create a small memory filesystem with [`mount_mfs(8)`][mfs] |
| 72 | upon which `/var/www/dev` will be mounted so that the `random` and |
| 73 | `null` device files can be created. |
| 74 | |
| 75 | ```console |
| 76 | $ doas mkdir /var/www/dev |
| 77 | $ doas mount_mfs -s 1M /dev/sd0b /var/www/dev |
| 78 | $ doas cd /var/www/dev |
| @@ -83,35 +85,36 @@ | |
| 85 | crw-r--r-- 1 root wheel 45, 0 Jun 18 06:30 urandom |
| 86 | ``` |
| 87 | |
| 88 | [mfs]: https://man.openbsd.org/mount_mfs.8 |
| 89 | |
| 90 | To make the mountable memory filesystem permanent, open `/etc/fstab` as |
| 91 | a privileged user and add the following line to automate creation of the |
| 92 | filesystem at startup: |
| 93 | |
| 94 | ```console |
| 95 | swap /var/www/dev mfs rw,-s=1048576 0 0 |
| 96 | ``` |
| 97 | |
| 98 | The same user that executes the fossil binary must have writable access |
| 99 | to the repository directory that resides within the chroot; on OpenBSD |
| 100 | this is `www`. In addition, grant repository directory ownership to the |
| 101 | user who will push to, pull from, and create repositories. |
| 102 | |
| 103 | ```console |
| 104 | $ doas chown -R user:www /var/www/htdocs/fsl.domain.tld |
| 105 | $ doas chmod 775 /var/www/htdocs/fsl.domain.tld |
| 106 | ``` |
| 107 | |
| 108 | ## <a name="httpdconfig"></a>Configure httpd |
| 109 | |
| 110 | On OpenBSD, [httpd.conf(5)][httpd] is the configuration file for |
| 111 | `httpd`. To setup the server to serve all Fossil repositores within the |
| 112 | directory specified in the CGI script, and automatically redirect |
| 113 | standard HTTP requests to HTTPS—apart from [Let's Encrypt][LE] |
| 114 | challenges issued in response to [acme-client(1)][acme] certificate |
| 115 | requests—create `/etc/httpd.conf` as a privileged user with the |
| 116 | following contents. |
| 117 | |
| 118 | [LE]: https://letsencrypt.org |
| 119 | [acme]: https://man.openbsd.org/acme-client.1 |
| 120 | [httpd.conf(5)]: https://man.openbsd.org/httpd.conf.5 |
| @@ -143,11 +146,10 @@ | |
| 146 | max-age 15768000 |
| 147 | preload |
| 148 | subdomains |
| 149 | } |
| 150 | connection max request body 104857600 |
| 151 | location "/*" { |
| 152 | fastcgi { param SCRIPT_FILENAME "/cgi-bin/scm" } |
| 153 | } |
| 154 | location "/.well-known/acme-challenge/*" { |
| 155 | root "/acme" |
| @@ -155,21 +157,21 @@ | |
| 157 | } |
| 158 | } |
| 159 | ``` |
| 160 | |
| 161 | **NOTE:** If not already in possession of a HTTPS certificate, comment |
| 162 | out the `https` server block and proceed to securing a free |
| 163 | [Let's Encrypt Certificate](#letsencrypt); otherwise skip to |
| 164 | [Start `httpd`](#starthttpd). |
| 165 | |
| 166 | ## <a name="letsencrypt"></a>Let's Encrypt Certificate |
| 167 | |
| 168 | In order for `httpd` to serve HTTPS, secure a free certificate from |
| 169 | Let's Encrypt using `acme-client`. Before issuing the request, however, |
| 170 | ensure you have a zone record for the subdomain with your registrar or |
| 171 | nameserver. Then open `/etc/acme-client.conf` as a privileged user to |
| 172 | configure the request. |
| 173 | |
| 174 | ```dosini |
| 175 | authority letsencrypt { |
| 176 | api url "https://acme-v02.api.letsencrypt.org/directory" |
| 177 | account key "/etc/acme/letsencrypt-privkey.pem" |
| @@ -187,13 +189,15 @@ | |
| 189 | domain full chain certificate "/etc/ssl/domain.tld.fullchain.pem" |
| 190 | sign with letsencrypt |
| 191 | } |
| 192 | ``` |
| 193 | |
| 194 | Start `httpd` with the new configuration file, and issue the certificate |
| 195 | request. |
| 196 | |
| 197 | ```console |
| 198 | $ doas rcctl start httpd |
| 199 | $ doas acme-client -vv domain.tld |
| 200 | acme-client: /etc/acme/letsencrypt-privkey.pem: account key exists (not creating) |
| 201 | acme-client: /etc/acme/letsencrypt-privkey.pem: loaded RSA account key |
| 202 | acme-client: /etc/ssl/private/domain.tld.key: generated RSA domain key |
| 203 | acme-client: https://acme-v01.api.letsencrypt.org/directory: directories |
| @@ -203,12 +207,12 @@ | |
| 207 | acme-client: /etc/ssl/domain.tld.crt: created |
| 208 | acme-client: /etc/ssl/domain.tld.fullchain.pem: created |
| 209 | ``` |
| 210 | |
| 211 | A successful result will output the public certificate, full chain of |
| 212 | trust, and private key into the `/etc/ssl` directory as specified in |
| 213 | `acme-client.conf`. |
| 214 | |
| 215 | ```console |
| 216 | $ doas ls -lR /etc/ssl |
| 217 | -r--r--r-- 1 root wheel 2.3K Mar 2 01:31:03 2018 domain.tld.crt |
| 218 | -r--r--r-- 1 root wheel 3.9K Mar 2 01:31:03 2018 domain.tld.fullchain.pem |
| @@ -215,21 +219,21 @@ | |
| 219 | |
| 220 | /etc/ssl/private: |
| 221 | -r-------- 1 root wheel 3.2K Mar 2 01:31:03 2018 domain.tld.key |
| 222 | ``` |
| 223 | |
| 224 | Make sure to reopen `/etc/httpd.conf` to uncomment the second server |
| 225 | block responsible for serving HTTPS requests before proceeding. |
| 226 | |
| 227 | ## <a name="starthttpd"></a>Start `httpd` |
| 228 | |
| 229 | With `httpd` configured to serve Fossil repositories out of |
| 230 | `/var/www/htdocs/fsl.domain.tld`, and the certificates and key in place, |
| 231 | enable and start `slowcgi`—OpenBSD's FastCGI wrapper server that will |
| 232 | execute the above Fossil CGI script—before checking that the syntax of |
| 233 | the `httpd.conf` configuration file is correct, and (re)starting the |
| 234 | server (if still running from requesting a Let's Encrypt certificate). |
| 235 | |
| 236 | ```console |
| 237 | $ doas rcctl enable slowcgi |
| 238 | $ doas rcctl start slowcgi |
| 239 | slowcgi(ok) |
| @@ -240,13 +244,12 @@ | |
| 244 | ``` |
| 245 | |
| 246 | ## <a name="clientconfig"></a>Configure Client |
| 247 | |
| 248 | To facilitate creating new repositories and pushing them to the server, |
| 249 | add the following function to your `~/.cshrc` or `~/.zprofile` or the |
| 250 | config file for whichever shell you are using on your development box. |
| 251 | |
| 252 | ```sh |
| 253 | finit() { |
| 254 | fossil init $1.fossil && \ |
| 255 | chmod 664 $1.fossil && \ |
| @@ -257,26 +260,26 @@ | |
| 260 | chmod 644 $1.fossil && \ |
| 261 | fossil ui |
| 262 | } |
| 263 | ``` |
| 264 | |
| 265 | This enables a new repository to be made with `finit repo`, which will |
| 266 | create the fossil repository file `repo.fossil` in the current working |
| 267 | directory; by default, the repository user is set to the environment |
| 268 | variable `$USER`. It then opens the repository and sets the user |
| 269 | password to the `$PASSWD` environment variable (which you can either set |
| 270 | with `export PASSWD 'password'` on the command line or add to a |
| 271 | *secured* shell environment file), and the `remote-url` to |
| 272 | `https://fsl.domain.tld/repo` with the credentials of `$USER` who is |
| 273 | authenticated with `$PASSWD`. Finally, it `rsync`'s the file to the |
| 274 | server before opening the local repository in your browser where you can |
| 275 | adjust settings such as anonymous user access, and set pertinent |
| 276 | repository details. Thereafter, you can add files with `fossil add`, and |
| 277 | commit with `fossil ci -m 'commit message'` where Fossil, by default, |
| 278 | will push to the `remote-url`. It's suggested you read the |
| 279 | [Fossil documentation][documentation]; with a sane and consistent |
| 280 | development model, the system is much more efficient and cohesive than |
| 281 | `git`—so the learning curve is not steep at all. |
| 282 | |
| 283 | [documentation]: https://fossil-scm.org/home/doc/trunk/www/permutedindex.html |
| 284 | |
| 285 | *[Return to the top-level Fossil server article.](../)* |
| 286 |