| 1 | # Overview # |
| 2 | |
| 3 | These notes cover the creation of a server, hosted with Linode, running Debian |
| 4 | Linux, offering the following services: |
| 5 | |
| 6 | - Mail server |
| 7 | |
| 8 | - SMTP via postfix |
| 9 | |
| 10 | - IMAP via dovecot |
| 11 | |
| 12 | - Realtime blacklists for SPAM rejection |
| 13 | |
| 14 | - MySQL for virtual domain and user management. |
| 15 | |
| 16 | - Web server |
| 17 | |
| 18 | - Apache as central HTTP server with multiple vhosts. |
| 19 | |
| 20 | - [CMless](http://git.subgeniuskitty.com/cmless/.git) as CGI for content management |
| 21 | |
| 22 | - ACME for automated SSL certificate management |
| 23 | |
| 24 | - Git server |
| 25 | |
| 26 | - SSH-based, authenticated read-write access to all git repositories |
| 27 | |
| 28 | - Anonymous read-only access to a subset of git repositories via: |
| 29 | |
| 30 | - Customized [gitweb](http://git.subgeniuskitty.com/gitweb-sgk/.git) for |
| 31 | GUI git browsing with syntax highlighting, diffs, etc |
| 32 | |
| 33 | - Git-daemon for cloning repositories via the `git://` protocol |
| 34 | |
| 35 | These notes are a high-level checklist for my reference rather than a |
| 36 | step-by-step installation guide for the public. That means they make no attempt |
| 37 | to explain all options at each step, rather that they mention only the options |
| 38 | I use on my servers. It also means they use my domains, my file system paths, |
| 39 | etc in the examples. |
| 40 | |
| 41 | |
| 42 | # TODO List # |
| 43 | |
| 44 | - Take a snapshot on Linode's backup service once the basic services are |
| 45 | operational. |
| 46 | |
| 47 | - Migrate mail server. Delete old linode vserver after downloading a disk image. |
| 48 | |
| 49 | - Finish this documentation. |
| 50 | |
| 51 | - Improve CSS on gitweb, especially for displaying READMEs. |
| 52 | |
| 53 | - Add some form of web logfile viewing. |
| 54 | |
| 55 | |
| 56 | # Basic Configuration # |
| 57 | |
| 58 | |
| 59 | ## General Information ## |
| 60 | |
| 61 | **Name:** SGK-Main-2020 |
| 62 | |
| 63 | **OS:** Debian 10 |
| 64 | |
| 65 | **Creation Date:** 2020-11-01 |
| 66 | |
| 67 | **Filesystem Points of Interest:** |
| 68 | |
| 69 | - `/srv/apache_vhosts`: Contains websites hosted by Apache2. See |
| 70 | `/etc/apache2/sites_available` for vhost configurations. |
| 71 | |
| 72 | - `/srv/git`: Master location for bare git repositories. All are private. |
| 73 | |
| 74 | - `/srv/gitweb_cache`: Contains checked out copies of git repositories from |
| 75 | `/srv/git`, publicly visible via `gitweb` and cloneable via `git-daemon`. |
| 76 | |
| 77 | |
| 78 | ## Preparation ## |
| 79 | |
| 80 | Setup DNS entries for `subgeniuskitty.com` and `logicavalanche.com` through |
| 81 | Linode. Remember to do IPv4 and IPv6 entries for the bare domain, `www`, |
| 82 | `mail`, and `git`. |
| 83 | |
| 84 | Create a new Debian 10 on Linode and update the system with `apt-get update && |
| 85 | apt-get upgrade`. |
| 86 | |
| 87 | Add a user via `adduser ataylor` and following the prompts. Edit |
| 88 | `/etc/ssh/sshd_config` to set `PermitRootLogin: no` and restart SSH. For both |
| 89 | the `ataylor` user and `root`, add the line `set mouse=` to `~/.vimrc` in order |
| 90 | to disable mouse support in `vim`, allowing normal mark-and-paste in the |
| 91 | terminal. |
| 92 | |
| 93 | Install useful packages: |
| 94 | |
| 95 | apt-get install net-tools screen bzip2 zip |
| 96 | |
| 97 | |
| 98 | # Web Server # |
| 99 | |
| 100 | |
| 101 | ## HTTP: Apache2 ## |
| 102 | |
| 103 | Install Apache2. |
| 104 | |
| 105 | apt-get install apache2 |
| 106 | |
| 107 | If not already defined elsewhere, add a `ServerName 127.0.0.1` entry to the |
| 108 | bottom of `/etc/apache2/apache2.conf`, or whatever is appropriate. |
| 109 | |
| 110 | Since we use `/srv` instead of `/var/www`, edit `/etc/apache2/apache2.conf` to |
| 111 | comment out the `<Directory ...>` entry for `/var/www` and replace it with |
| 112 | this: |
| 113 | |
| 114 | <Directory /srv/> |
| 115 | Options Indexes FollowSymLinks |
| 116 | AllowOverride None |
| 117 | Require all granted |
| 118 | </Directory> |
| 119 | |
| 120 | Make and edit the file `/srv/apache_vhosts/default/index.html` with (rewritten) |
| 121 | contents: |
| 122 | |
| 123 | <p>Invalid VHost</p> |
| 124 | <p>Contact user @at@ domain .dot. com</p> |
| 125 | |
| 126 | Ensure everything under `/srv/apache_vhosts`, including that directory itself, |
| 127 | is owned recursively by `www-data:www-data`. |
| 128 | |
| 129 | Edit `/etc/apache2/sites-available/000-default.conf` and |
| 130 | `/etc/apache2/sites-available/000-default.conf`, changing references for the |
| 131 | default sites from `/var/www/...` to `/srv/apache_vhosts/...` as necessary. |
| 132 | |
| 133 | Reload Apache2 with `systemctl reload apache2` and check status with `systemctl |
| 134 | status apache2`. |
| 135 | |
| 136 | |
| 137 | ### SSL ### |
| 138 | |
| 139 | Install certbot and generate a key for its use. |
| 140 | |
| 141 | apt-get install certbot |
| 142 | openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 |
| 143 | |
| 144 | Create `/etc/apache2/conf-available/ssl-params.conf` with the following |
| 145 | contents. |
| 146 | |
| 147 | SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 |
| 148 | SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 |
| 149 | SSLHonorCipherOrder off |
| 150 | SSLSessionTickets off |
| 151 | |
| 152 | SSLUseStapling On |
| 153 | SSLStaplingCache "shmcb:logs/ssl_stapling(32768)" |
| 154 | |
| 155 | Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" |
| 156 | Header always set X-Frame-Options SAMEORIGIN |
| 157 | Header always set X-Content-Type-Options nosniff |
| 158 | |
| 159 | SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem" |
| 160 | |
| 161 | Enable the new configuration and required mods, then restart Apache2. |
| 162 | |
| 163 | a2enconf ssl-params |
| 164 | a2enmod ssl |
| 165 | a2enmod headers |
| 166 | systemctl restart apache2 |
| 167 | |
| 168 | Retrieve an initial certificate with the following command, modified to match |
| 169 | the desired webroot and server names. |
| 170 | |
| 171 | <http://subgeniuskitty.com> and <http://logicavalanche.com>: |
| 172 | |
| 173 | certbot certonly --agree-tos --email webmaster@subgeniuskitty.com --webroot -w /srv/apache_vhosts/subgeniuskitty.com/site/data/ -d subgeniuskitty.com -d www.subgeniuskitty.com |
| 174 | |
| 175 | <http://archive.subgeniuskitty.com> and <http://git.subgeniuskitty.com>: |
| 176 | |
| 177 | certbot certonly --agree-tos --email webmaster@subgeniuskitty.com --webroot -w /srv/apache_vhosts/archive.subgeniuskitty.com/ -d archive.subgeniuskitty.com |
| 178 | |
| 179 | Edit `/etc/apache2/sites-available/subgeniuskitty.com`, adding the following |
| 180 | `VirtualHost` definition that mostly copies the non-SSL entry. |
| 181 | |
| 182 | <VirtualHost *:443> |
| 183 | SSLEngine on |
| 184 | SSLCertificateFile /etc/letsencrypt/live/subgeniuskitty.com/fullchain.pem |
| 185 | SSLCertificateKeyFile /etc/letsencrypt/live/subgeniuskitty.com/privkey.pem |
| 186 | |
| 187 | ...copy of vhost definition for host *:80... |
| 188 | </VirtualHost> |
| 189 | |
| 190 | Edit `/etc/cron.d/certbot` and append `--renew-hook "systemctl reload apache2"` |
| 191 | to the certbot invokation. |
| 192 | |
| 193 | Test with `certbot renew --dry-run`. |
| 194 | |
| 195 | Repeat the process for any other sites hosted on this server. |
| 196 | |
| 197 | Backup the `/etc/letsencrypt` folder off-server periodically. |
| 198 | |
| 199 | |
| 200 | ## Basic Website ## |
| 201 | |
| 202 | Using <http://archive.subgeniuskitty.com> as an example of a basic website, |
| 203 | create an Apache2 vhost configuration file at |
| 204 | `/etc/apache2/sites-available/archive.subgeniuskitty.com.conf`. |
| 205 | |
| 206 | <VirtualHost *:80> |
| 207 | DocumentRoot "/srv/apache_vhosts/archive.subgeniuskitty.com" |
| 208 | ServerName archive.subgeniuskitty.com |
| 209 | ServerAdmin webmaster@subgeniuskitty.com |
| 210 | ErrorLog /var/log/apache2/error_log.archive.subgeniuskitty.com |
| 211 | CustomLog /var/log/apache2/access_log.archive.subgeniuskitty.com combined |
| 212 | <Directory "/srv/apache_vhosts/archive.subgeniuskitty.com"> |
| 213 | Options +FollowSymLinks |
| 214 | AllowOverride None |
| 215 | Require all granted |
| 216 | </Directory> |
| 217 | <Directory "/srv/apache_vhosts/archive.subgeniuskitty.com/sites"> |
| 218 | Options +FollowSymLinks +Indexes |
| 219 | AllowOverride None |
| 220 | Require all granted |
| 221 | </Directory> |
| 222 | </VirtualHost> |
| 223 | |
| 224 | Make the directory `/srv/apache_vhosts/archive.subgeniuskitty.com`, move your |
| 225 | data into it, and ensure everything is owned by `www-data:www-data`. |
| 226 | |
| 227 | Enable the vhost with `a2ensite archive.subgeniuskitty.com` and `systemctl |
| 228 | reload apache2`. |
| 229 | |
| 230 | |
| 231 | ## CMless Website ## |
| 232 | |
| 233 | Enable `mod_rewrite` and either `mod_cgi` or `mod_cgid` as appropriate with |
| 234 | these commands. |
| 235 | |
| 236 | a2enmod rewrite |
| 237 | a2enmod cgid |
| 238 | |
| 239 | Install `discount` to convert Markdown to HTML. |
| 240 | |
| 241 | apt-get install discount |
| 242 | |
| 243 | Create `/etc/apache2/sites-available/subgeniuskitty.com.conf`. |
| 244 | |
| 245 | <VirtualHost *:80> |
| 246 | DocumentRoot "/srv/apache_vhosts/subgeniuskitty.com" |
| 247 | ServerName subgeniuskitty.com |
| 248 | ServerAlias www.subgeniuskitty.com |
| 249 | ServerAdmin webmaster@subgeniuskitty.com |
| 250 | ErrorLog /var/log/apache2/error_log.subgeniuskitty.com |
| 251 | CustomLog /var/log/apache2/access_log.subgeniuskitty.com combined |
| 252 | AddHandler cgi-script .py |
| 253 | <Directory "/srv/apache_vhosts/subgeniuskitty.com"> |
| 254 | Options -ExecCGI -Indexes |
| 255 | AllowOverride None |
| 256 | Require all granted |
| 257 | </Directory> |
| 258 | <Directory "/srv/apache_vhosts/subgeniuskitty.com/bin"> |
| 259 | Options ExecCGI |
| 260 | AllowOverride None |
| 261 | Require all granted |
| 262 | </Directory> |
| 263 | RewriteEngine On |
| 264 | RewriteRule (.*) /srv/apache_vhosts/subgeniuskitty.com/site/data/$1 |
| 265 | RewriteCond %{REQUEST_FILENAME} !-f |
| 266 | RewriteRule .* /srv/apache_vhosts/subgeniuskitty.com/bin/cmless.py |
| 267 | </VirtualHost> |
| 268 | |
| 269 | Enable the site with `a2ensite subgeniuskitty.com`. |
| 270 | |
| 271 | Clone a copy of [CMless](http://git.subgeniuskitty.com/cmless/.git) into |
| 272 | `/srv/apache_vhosts/subgeniuskitty.com` and ensure everything is owned by |
| 273 | `www-data:www-data`. |
| 274 | |
| 275 | Clone a copy of [the website |
| 276 | data](http://git.subgeniuskitty.com/website_subgeniuskitty.com/.git) into |
| 277 | `/srv/apache_vhosts/subgeniuskitty.com/site`. Verify it is owned by |
| 278 | `ataylor:ataylor` (but still readable by all) so we can update the site |
| 279 | remotely with a simple script like this: |
| 280 | |
| 281 | #!/usr/local/bin/bash |
| 282 | # |
| 283 | # Usage: No cmdline arguments |
| 284 | # Update content of www.subgeniuskitty.com to the latest version. |
| 285 | |
| 286 | ssh ataylor@git.subgeniuskitty.com "cd /srv/apache_vhosts/subgeniuskitty.com/site && git pull" |
| 287 | |
| 288 | Reload Apache's configuration with `systemctl reload apache2` and test access |
| 289 | to the website. |
| 290 | |
| 291 | Repeat this process for <http://logicavalanche.com>. |
| 292 | |
| 293 | |
| 294 | # Git Server # |
| 295 | |
| 296 | The git server provides read-write access to a private collection of bare |
| 297 | repositories located at `/srv/git` via SSH. It also provides read-only access |
| 298 | to a public collection of normal repositories located at `/srv/gitweb_cache` |
| 299 | via <http://git.subgeniuskitty.com/repo_name> through gitweb and via |
| 300 | [git://git.subgeniuskitty.com/repo_name](git://git.subgeniuskitty.com/repo_name) |
| 301 | through `git-daemon`. |
| 302 | |
| 303 | |
| 304 | ## Read/Write: SSH ## |
| 305 | |
| 306 | Install git with `apt-get install git`. |
| 307 | |
| 308 | On my workstation, generate an SSH key with `ssh-keygen -t rsa`. |
| 309 | |
| 310 | On the server, as user `ataylor`: |
| 311 | |
| 312 | mkdir ~/.ssh |
| 313 | chmod 700 ~/.ssh |
| 314 | touch ~/.ssh/authorized_keys |
| 315 | chmod 600 ~/.ssh/authorized_keys |
| 316 | |
| 317 | Then `cat` the public SSH key from the workstation to the server, appending it |
| 318 | onto `~/.ssh/authorized_keys`. |
| 319 | |
| 320 | Verify ability to login using new certificate. |
| 321 | |
| 322 | Create a directory `/srv/git` owned by `ataylor:ataylor`. This will hold bare |
| 323 | git repositories and act as the central private store for SGK git repos. |
| 324 | |
| 325 | From the workstation, we can create a new bare repository on the server. For |
| 326 | example, packed up in a simple script: |
| 327 | |
| 328 | #!/usr/local/bin/bash |
| 329 | # |
| 330 | # Usage: sgkgit-new-repo project_name |
| 331 | # Setup a repository on the SGK git server. |
| 332 | |
| 333 | if [ "$#" -ne 1 ]; then |
| 334 | echo "Must specify repo name as only parameter." |
| 335 | exit 2 |
| 336 | fi |
| 337 | |
| 338 | ssh ataylor@git.subgeniuskitty.com "git init --bare /srv/git/$@" |
| 339 | |
| 340 | We then set the remote of an existing repository to the new bare repository. |
| 341 | Again as a script: |
| 342 | |
| 343 | #!/usr/local/bin/bash |
| 344 | # |
| 345 | # Usage: sgkgit-set-origin project_name |
| 346 | # Sets remote to the correct path for 'project_name' on the SGK git server. |
| 347 | |
| 348 | if [ "$#" -ne 1 ]; then |
| 349 | echo "Must specify repo name as only parameter." |
| 350 | exit 2 |
| 351 | fi |
| 352 | |
| 353 | git remote remove origin |
| 354 | git remote add origin ataylor@git.subgeniuskitty.com:/srv/git/$@ |
| 355 | echo "Remember to make the first push with \"git push --set-upstream origin master\"." |
| 356 | |
| 357 | After the first push to the bare repository on the server, simply `git push` |
| 358 | and `git pull` as normal. |
| 359 | |
| 360 | You can also list the repositories currently on the server with simple SSH commands. |
| 361 | |
| 362 | #!/usr/local/bin/bash |
| 363 | # |
| 364 | # Usage: No cmdline arguments. |
| 365 | # List all remote repos available on SGK git server. |
| 366 | |
| 367 | ssh ataylor@git.subgeniuskitty.com "ls -lt /srv/git/" |
| 368 | |
| 369 | Clone one of these repositories, with remote correspondingly pre-set. |
| 370 | |
| 371 | #!/usr/local/bin/bash |
| 372 | # |
| 373 | # Usage: sgkgit-checkout project_name |
| 374 | # Clone a local copy of repo "project_name" from SGK git server. |
| 375 | |
| 376 | if [ "$#" -ne 1 ]; then |
| 377 | echo "Must specify repo name as only parameter." |
| 378 | exit 2 |
| 379 | fi |
| 380 | |
| 381 | git clone ataylor@git.subgeniuskitty.com:/srv/git/$@ |
| 382 | |
| 383 | |
| 384 | ## Read-Only: Gitweb ## |
| 385 | |
| 386 | Enable `mod_rewrite` and either `mod_cgi` or `mod_cgid` as appropriate with |
| 387 | these commands. |
| 388 | |
| 389 | a2enmod rewrite |
| 390 | a2enmod cgid |
| 391 | |
| 392 | Install `discount` to convert Markdown to HTML, `highlight` for syntax |
| 393 | highlighting, and `gitweb` to pull in any dependencies. |
| 394 | |
| 395 | apt-get install discount highlight gitweb |
| 396 | |
| 397 | Create `/etc/apache2/sites-available/git.subgeniuskitty.com.conf`. |
| 398 | |
| 399 | <VirtualHost *:80> |
| 400 | ServerName git.subgeniuskitty.com |
| 401 | ServerAdmin webmaster@subgeniuskitty.com |
| 402 | |
| 403 | DocumentRoot "/srv/apache_vhosts/git.subgeniuskitty.com" |
| 404 | |
| 405 | ErrorLog /var/log/apache2/error_log.git.subgeniuskitty.com |
| 406 | CustomLog /var/log/apache2/access_log.git.subgeniuskitty.com combined |
| 407 | |
| 408 | <Directory "/srv/apache_vhosts/git.subgeniuskitty.com"> |
| 409 | Options +FollowSymLinks +ExecCGI |
| 410 | AllowOverride None |
| 411 | Require all granted |
| 412 | AddHandler cgi-script .cgi |
| 413 | DirectoryIndex gitweb.cgi |
| 414 | RewriteEngine On |
| 415 | RewriteCond %{REQUEST_FILENAME} !-f |
| 416 | RewriteCond %{REQUEST_FILENAME} !-d |
| 417 | RewriteRule ^.* /gitweb.cgi/$0 [L,PT] |
| 418 | </Directory> |
| 419 | </VirtualHost> |
| 420 | |
| 421 | Enable the site with `a2ensite git.subgeniuskitty.com`. |
| 422 | |
| 423 | Clone a copy of [the SGK gitweb fork](http://git.subgeniuskitty.com/gitweb-sgk/.git) |
| 424 | into `/srv/apache_vhosts/git.subgeniuskitty.com` and ensure everything is owned |
| 425 | by `ataylor:ataylor` (but world-readable!) so we can update via SSH with a script like this. |
| 426 | |
| 427 | #!/usr/local/bin/bash |
| 428 | # |
| 429 | # Usage: No cmdline arguments |
| 430 | # Update git.subgeniuskitty.com to the latest version of forked gitweb repo. |
| 431 | |
| 432 | ssh ataylor@git.subgeniuskitty.com "cd /srv/apache_vhosts/git.subgeniuskitty.com && git pull" |
| 433 | |
| 434 | This fork makes a few changes to gitweb, displaying READMEs by default, etc. |
| 435 | Read the gitweb project's `README.md` for more details. |
| 436 | |
| 437 | Create a gitweb config file at `/etc/gitweb.conf`. Note that we are adding a |
| 438 | `clone url` to the toolbar with the address of our `git-daemon` server. |
| 439 | Remember to set that up. |
| 440 | |
| 441 | $site_name = "git.subgeniuskitty.com"; |
| 442 | @git_base_url_list = ("git://git.subgeniuskitty.com"); |
| 443 | $projectroot = "/srv/gitweb_cache"; |
| 444 | $git_temp = "/tmp"; |
| 445 | |
| 446 | @stylesheets = ("static/gitweb.css"); |
| 447 | $javascript = "static/gitweb.js"; |
| 448 | $logo = "static/sgk-logo.png"; |
| 449 | $favicon = "static/git-favicon.png"; |
| 450 | |
| 451 | # git-diff-tree(1) options to use for generated patches |
| 452 | @diff_opts = (); |
| 453 | |
| 454 | # Enable PATH_INFO so the server can produce URLs of the |
| 455 | # form: http://git.hokietux.net/project.git/xxx/xxx |
| 456 | # This allows for pretty URLs *within* the Git repository, |
| 457 | # also needs the Apache rewrite rules for full effect. |
| 458 | $feature{'pathinfo'}{'default'} = [1]; |
| 459 | |
| 460 | # HTML text to include as home page header. |
| 461 | $home_text = "indextext.html"; |
| 462 | |
| 463 | # Add a toolbar option with the 'git clone url'. |
| 464 | $feature{'actions'}{'default'} = [('clone url', 'git://git.subgeniuskitty.com/%n', 'summary')]; |
| 465 | |
| 466 | # Category name is read from .git/category, in the same manner as .git/description. |
| 467 | $projects_list_group_categories = 1; |
| 468 | $project_list_default_category = "misc"; |
| 469 | |
| 470 | # Needed for displaying README files. |
| 471 | $prevent_xss = 0; |
| 472 | |
| 473 | # Enable syntax highlighting. |
| 474 | $feature{'highlight'}{'default'} = [1]; |
| 475 | |
| 476 | ################################################################################ |
| 477 | |
| 478 | # Enable blame, pickaxe search, snapshop, search, and grep |
| 479 | # support, but still allow individual projects to turn them off. |
| 480 | # These are features that users can use to interact with your Git trees. They |
| 481 | # consume some CPU whenever a user uses them, so you can turn them off if you |
| 482 | # need to. Note that the 'override' option means that you can override the |
| 483 | # setting on a per-repository basis. |
| 484 | $feature{'blame'}{'default'} = [1]; |
| 485 | $feature{'blame'}{'override'} = [1]; |
| 486 | |
| 487 | $feature{'pickaxe'}{'default'} = [1]; |
| 488 | $feature{'pickaxe'}{'override'} = [1]; |
| 489 | |
| 490 | $feature{'snapshot'}{'default'} = [1]; |
| 491 | $feature{'snapshot'}{'override'} = [1]; |
| 492 | |
| 493 | $feature{'search'}{'default'} = [1]; |
| 494 | |
| 495 | $feature{'grep'}{'default'} = [1]; |
| 496 | $feature{'grep'}{'override'} = [1]; |
| 497 | |
| 498 | Create the directory `/srv/gitweb_cache`. It should be readable by the web |
| 499 | server (`www-data`), but owned by `ataylor:ataylor` so that simple scripts like |
| 500 | the following can make repositories public/private. |
| 501 | |
| 502 | #!/usr/local/bin/bash |
| 503 | # |
| 504 | # Usage: sgkgit-make-public project_name |
| 505 | # Make a repo accessible through gitweb and git-daemon. |
| 506 | |
| 507 | if [ "$#" -ne 1 ]; then |
| 508 | echo "Must specify repo name as only parameter." |
| 509 | exit 2 |
| 510 | fi |
| 511 | |
| 512 | read -p "Enter a category name: " category |
| 513 | read -p "Enter a description: " description |
| 514 | |
| 515 | echo "You entered:" |
| 516 | printf "\tCategory: $category \n" |
| 517 | printf "\tDescription: $description \n" |
| 518 | read -p "Confirm (y/n)?: " confirm |
| 519 | |
| 520 | if [ "$confirm" == "y" ]; then |
| 521 | ssh ataylor@git.subgeniuskitty.com "cd /srv/gitweb_cache && rm -rf $@ && git clone /srv/git/$@" |
| 522 | ssh ataylor@git.subgeniuskitty.com "cd /srv/git && \ |
| 523 | printf '#!/usr/bin/bash\ncd /srv/gitweb_cache/$@\ngit --git-dir=.git pull\n' > \ |
| 524 | /srv/git/$@/hooks/post-update && chmod +x /srv/git/$@/hooks/post-update" |
| 525 | ssh ataylor@git.subgeniuskitty.com "echo \"$category\" > /srv/gitweb_cache/$@/.git/category" |
| 526 | ssh ataylor@git.subgeniuskitty.com "echo \"$description\" > /srv/gitweb_cache/$@/.git/description" |
| 527 | fi |
| 528 | |
| 529 | In addition to cloning the git repo into `/srv/gitweb_cache` from the private, |
| 530 | SSH-only collection of repositories in `/srv/git`, this also creates a |
| 531 | `post-update` hook in the bare repo in `/srv/git` to ensure that gitweb's cache |
| 532 | is updated every time a push is made via SSH to the private repo. |
| 533 | |
| 534 | This script also sets the `.git/description` and `.git/category` files needed |
| 535 | by gitweb for displays like the project summary page. These are not under |
| 536 | version control and may be directly edited to change what is displayed in |
| 537 | gitweb. |
| 538 | |
| 539 | We can remove the public cache, making the repo private-only as shown in this |
| 540 | script. |
| 541 | |
| 542 | #!/usr/local/bin/bash |
| 543 | # |
| 544 | # Usage: sgkgit-make-private project_name |
| 545 | # Make a repo inaccessible through gitweb and git-daemon. |
| 546 | |
| 547 | if [ "$#" -ne 1 ]; then |
| 548 | echo "Must specify repo name as only parameter." |
| 549 | exit 2 |
| 550 | fi |
| 551 | |
| 552 | ssh ataylor@git.subgeniuskitty.com "rm -rf /srv/gitweb_cache/$@ && rm /srv/git/$@/hooks/post-update" |
| 553 | |
| 554 | Any repos made private/public via this method are immediately reflected in |
| 555 | `gitweb` and `git-daemon`. |
| 556 | |
| 557 | |
| 558 | ## Read-Only: Git Daemon ## |
| 559 | |
| 560 | Since `git` was already installed, simply create a new service profile in |
| 561 | `/etc/systemd/system/git-daemon.service`. |
| 562 | |
| 563 | [Unit] |
| 564 | Description=Start Git Daemon |
| 565 | |
| 566 | [Service] |
| 567 | ExecStart=/usr/bin/git daemon --export-all --reuseaddr --base-path=/srv/gitweb_cache/ /srv/gitweb_cache/ |
| 568 | |
| 569 | Restart=always |
| 570 | RestartSec=500ms |
| 571 | |
| 572 | StandardOutput=syslog |
| 573 | StandardError=syslog |
| 574 | SyslogIdentifier=git-daemon |
| 575 | |
| 576 | User=ataylor |
| 577 | Group=ataylor |
| 578 | |
| 579 | [Install] |
| 580 | WantedBy=multi-user.target |
| 581 | |
| 582 | Then start the service with `systemctl daemon-reload` and `systemctl start |
| 583 | git-daemon`. Verify functionality before enabling daemon-autostart with |
| 584 | `systemctl enable git-daemon`. |
| 585 | |
| 586 | The `--export-all` flag tells `git-daemon` to export all repositories located |
| 587 | at the specified path, regardless of the presence (or lack) of the file |
| 588 | `.git/git-daemon-export-ok` in the individual repository. We do this because |
| 589 | only public repos are checked out to this folder. All private repos are kept |
| 590 | entirely elsewhere. |
| 591 | |
| 592 | The directory `/srv/gitweb_cache` should have already been created when |
| 593 | installing gitweb. If not, go read those instructions. |
| 594 | |
| 595 | A repository located at `/srv/gitweb_cache/repo_name` may be cloned through |
| 596 | `git-daemon` at |
| 597 | [git://git.subgeniuskitty.com/repo_name](git://git.subgeniuskitty.com/repo_name) |
| 598 | with `git clone`. |
| 599 | |
| 600 | |
| 601 | # Mail Server # |
| 602 | |
| 603 | TODO |
| 604 | |
| 605 | TODO |
| 606 | |
| 607 | TODO |
| 608 | |
| 609 | TODO |
| 610 | |
| 611 | TODO |
| 612 | |
| 613 | TODO |
| 614 | |
| 615 | TODO |
| 616 | |
| 617 | TODO |
| 618 | |