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