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