URI: 
       # Host a website (httpd)
       
       Host you own website is a great project! πŸ˜„ It's the best way to have 
       your personal space to do whatever you want without restrictions.
       
       OpenBSD is shipped with "httpd", a http server. It is light and easy to 
       configure. Most of the time, it is more than enough, but if you need 
       even more features, look for "nginx" or "apache" in ports.
       
       In this part, we'll see how to host a simple static website, then how 
       to add PHP support to finally show some web applications examples.
       
       Before going any further, take note that http is chrooted in /var/www 
       by default.
       
       > What is that supposed to mean ?
       
       To httpd, every file "above" /var/www can't be read. In other words, 
       httpd see /var/www as the new root /. For obvious security reasons, if 
       httpd can't even reach system files, it reduce the risk that someone 
       find sensitive data through a weak website.
       
       ## Simple static website
       
       A static website is just a few HTML files served by httpd. It's safe 
       and fast. That's a good starting point. Let's see how to host you own 
       website.
       
       First, create a directory to store the website :
       
       ```
       # mkdir /var/www/htdocs/my_website
       ```
       
       Now, copy your website html pages and files in that directory 
       (index.html...). Just make sure httpd is able to read those files by 
       adjusting permissions with "chmod a+r" or set the owner to www:
       
       ```
       # chown -R www:daemon /var/www/htdocs/my_website
       ```
       
       You might consider fine tuning permissions later. πŸ˜‰
       
       Now you must configure httpd to add a new section for your website. If 
       it is served on http://athome.tld, you'll edit /etc/httpd.conf (copied 
       from /etc/examples/httpd.conf if you want) so it looks like this :
       
       ```
       types { include "/usr/share/misc/mime.types" }
       
       server "athome.tld" {
           listen on * port 80
           root "/htdocs/my_website"
       }
       ```
       
       A few notes about the previous lines :
       
       * types ...: This first line add more mimetypes to the default known by 
         httpd. It helps clients to open the files you serve on your website 
         with the appropriate software.
       * server "athome.tld" {: Open a new section concerning the domain 
         "athome.tld". As you might guess, you can serve multiple domains if you 
         add more sections.
       * listen ...: the server listen on every ip and interfaces (*) on the 
         default http port.
       * root ...: location where are the files stored, relative to the 
         chroot. Remember, to httpd, /var/www is /.
       
       You can now enable and start httpd :
       
       ```
       # rcctl enable httpd
       # rcctl start httpd
       ```
       
       Check http port (80) is open in your router and firewall, then check 
       your website is reachable.
       
       Every file you add in /var/www/htdocs/my_website will be served.
       
       You can use SFTP previously described to upload your website πŸ˜‰.
       
       ## Get a SSL certificate
       
       SSL certificates allow to make TLS encryption and thus, among other 
       things, serve your website through a more secure protocol HTTPS.
       
       It is necessary when sensitive data like passwords is sent to/from your 
       server.
       
       However, (very) old computers don't support TLS. If you're a 
       permacomputing adept, you may want to keep a simple HTTP access aside 
       of HTTPS. 
       
       ### Letsencrypt
       
  HTML "Let's Encrypt" is a free certificate authority providing easy to use  API to get and manage certificates.
       There is a client included in OpenBSD named "acme-client" to deal with 
       such tasks. It currently requires a http server to generate 
       certificates. That's why we'll discuss acme-client here. However, you 
       certainly can use those certificates for other needs that https such as 
       IMAPS.
       
       ! First of all, check you opened port 80 in the firewall and eventually 
       in your router. Acme-client needs to check for some files you'll make 
       available for letsencrypt with httpd.
       
       Actually, acme-client will ensure you manage the domain you request a 
       certificate for. To do so, it ask an unique file to Let's Encrypt, 
       kinda fingerprint, stored in "/var/www/acme". Then, Let's Encrypt try 
       to get this "secret" file on your server at 
       ".well-known/acme-challenge", asking for 
  HTML succeeds, the request is accepted and you get a certificate. Finally  the file is deleted.
       Remember your website is probably located in "/var/www/htdocs/website" 
       or something. You need to make "/var/www/acme" for letsencrypt to get 
       the secret file. So, add a "location" instruction in "/etc/httpd.conf" :
       
       ```
       server "athome.tld" {
           listen on * port 80
       
           location "/.well-known/acme-challenge/*" {
               root "/acme"
               request strip 2
           }
           root "/htdocs/website"
       }
       ```
       
       A few explanations :
       
       * location "/.well-known/acme-challenge/* {: we add new instructions 
         when a client ask for any file (*) in /.well-known/acme-challenge.
       * root "/acme": in this scenario, a new root is defined: /var/www/acme. 
         This the place acme-client store files needed by letsencrypt.
       * request strip 2: we remove the .well-known/acme-challenge in the 
         request made by the client so it leads to /var/www/acme/requested-file.
       
       ! This section will have to be added for every domain served by httpd, 
       even alternative names specified in the acme-client configuration file 
       below. You might find easier to use "include" instruction in 
       "httpd.conf" later as it is described in the "Tips" part a bit further 
       πŸ˜‰.
       
       Before calling acme-client, you must configure it by editing 
   DIR template.
       For the example, the file might look like this :
       
       ```
       authority letsencrypt {
         api url "https://acme-v02.api.letsencrypt.org/directory"
         account key "/etc/acme/letsencrypt-privkey.pem"
       }
       
       authority letsencrypt-staging {
         api url "https://acme-staging-v02.api.letsencrypt.org/directory"
         account key "/etc/acme/letsencrypt-staging-privkey.pem"
       }
       
       domain athome.tld {
           alternative names { webmail.athome.tld www.athome.tld }
           domain key "/etc/ssl/private/athome.tld.key"
           domain full chain certificate "/etc/ssl/athome.tld.crt"
           sign with letsencrypt
       }
       ```
       
       Of course, replace athome.tld, alternative names { ... with the other 
       domains and subdomains you need and eventually the location of key and 
       full chain certificate.
       
       Make sure necessary directories are here (they might already exist) :
       
       ```
       # mkdir -p -m 700 /etc/ssl/private
       # mkdir -p -m 755 /var/www/acme
       ```
       
       Check acme-client configuration with # acme-client -n, it must return 
       nothing if there are no errors.
       
       Now you can get your certificates :
       
       ```
       # acme-client -v athome.tld
       ```
       
       At first, you might want to make sure everything works as expected 
       using "sign with letsencrypt-staging" in /etc/acme-client.conf and 
       switch back to "sign with letsencrypt" later.
       You can force getting certificates using "acme-client -F athome.tld".
       
       Consider renewing certificates automatically using /etc/weekly.local. 
       It is a script executed every week.
       
       ```
   DIR ```
       Using &&, certificates are reloaded in httpd only if there are 
       successfully renewed certificates. If at some point other daemons than 
       httpd uses your certificates, you'll have to reload them too (relayd, 
       dovecot...)
       
       Now you've got a certificate, let's enable https in /etc/httpd.conf πŸ˜„. 
       A new "tls" section appears. :
       
       ```
       server "athome.tld" {
           listen on * port 80
           # http version
           # [...snip...]
       }
       # snippet of /etc/httpd.conf
       server "athome.tld" {
           listen on * tls port 443
           root "/htdocs/website"
       
           tls {
               certificate "/etc/ssl/athome.tld.crt"
               key "/etc/ssl/private/athome.tld.key"
           }
           hsts
       
           # add your website specific configuration here
       }
       ```
       
       As you can see, now httpd listens on port 443 (https): remember to 
       configure your firewall for this.
       
       You may want to redirect clients accessing from http to https.
       To do so, add an instruction matching all request ("location *") AFTER 
       the part for acme-client. The clients will be redirected to the https 
       version except if the request matched the previous one for acme-client.
       
       ```
       # snippet of /etc/httpd.conf
       server "athome.tld" {
           listen on * port 80
       
           location "/.well-known/acme-challenge/*" {
               root "/acme"
               request strip 2
           }
       
           location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
       }
       server "athome.tld" {
           listen on * tls port 443
           #[...]
       ```
       
       Remember to add such section for every website you want to serve. You 
       may want to use "include" instructions to ease your life. See next part 
       πŸ˜‰.
       
       ### About "include" usage in httpd.conf
       
       You will certainly enable tls for multiple website. Instead of 
       rewriting the same instructions again and again, you can include a file.
       
       First, create a directory to keep multiple httpd configuration files :
       
       ```
       # mkdir /etc/httpd.d
       ```
       
       Then, we create /etc/httpd.d/acme.conf to keep instructions related to 
       acme seen earlier :
       
       ```
       location "/.well-known/acme-challenge/*" {
           root "/acme"
           request strip 2
       }
       ```
       
       You even can go a bit further by creating /etc/httpd.d/tls.conf for 
       multiples lines about certificates :
       
       ```
       tls {
           certificate "/etc/ssl/athome.tld.crt"
           key "/etc/ssl/private/athome.tld.key"
       }
       hsts
       ```
       
       Now, /etc/httpd.conf can be simplified to those lines below. The whole 
       file let you serve 3 websites : athome.tld, www.athome.tld and 
       webmail.athome.tld :
       
       ```
       server "www.athome.tld" {
           listen on * tls port 443
           include "/etc/httpd.d/tls.conf"
           root "/htdocs/www.athome.tld"
       }
       
       server "www.athome.tld" {
           listen on * port 80
           include "/etc/httpd.d/acme.conf"
           location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
       }
       
       server "athome.tld" {
           listen on * tls port 443
           include "/etc/httpd.d/tls.conf"
           block return 301 "https://www.$SERVER_NAME$REQUEST_URI"
       }
       
       server "athome.tld" {
           listen on * port 80
           include "/etc/httpd.d/acme.conf"
           location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
       }
       
       server "webmail.athome.tld" {
           listen on * tls port 443
           include "/etc/httpd.d/tls.conf"
           root "/htdocs/webmail.athome.tld"
       }
       
       server "webmail.athome.tld" {
           listen on * port 80
           include "/etc/httpd.d/acme.conf"
           location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
       }
       ```
       
       The above configuration redirect from athome.tld to www.athome.tld. 
       Another website webmail.chez.tld is handled. For each domain, using 
       acme-client is possible.
       
       You may have noticed each section is quite a routine. You can imagine 
       other usages to include instruction if you need it.
       
       Thank you GrΓ©gory Marchal for your suggestions on this part. πŸ˜‰
       
       ### Generate a self-signed certificate
       
       You can generate your own self signed-certificate. At first connection, 
       clients will see a warning asking if they trust or not the certificate.
       
  HTML To do so, see man 8 ssl in section "Generating RSA server certificates".
       ### Facultative : CAA records
       
       You can add a CAA record in your DNS zone to show you own the domain 
       and YOU asked a certificate to Let's Encrypt. This is just a proof of 
       honesty helping someone to trust the certificate used.
       
       ```
       @ 300 IN   CAA   0 issue "letsencrypt.org"
       ```
       
       ### Check your server SSL configuration
       
       Find below a few tools to check how well you've configured your server 
       (not only https) :
       
  HTML URL:https://www.ssllabs.com/
  HTML URL:https://tls.imirhil.fr/
  HTML URL:https://observatory.mozilla.org/
       ## PHP
       
       ### The very minimal PHP support
       
       You may want to use PHP one day, especially if you use a CMS as example.
       
       Use OpenBSD's ports to install php (adjust the version number)
       
       ```
       # pkg_add php-7.9.7
       ```
       
       To see every PHP version availables :
       
       ```
       # pkg_info -Q php
       ```
       
       Then, enable and start php :
       
       ```
       # rcctl enable php74_fpm
       # rcctl start php74_fpm
       ```
       
       Here, "74" suggests you installed PHP version 7.9.
       
       Now edit httpd configuration so it sends php files to the interpreter. 
       In /etc/httpd.conf:
       
       ```
       server "athome.tld" {
               listen on * port 80
               root "/htdocs/website"
               directory index index.php
       
               location "*.php" {
                       fastcgi socket "/run/php-fpm.sock"
               }
       }
       ```
       
       Notice the directory index index.php instruction. By default, when 
       someone reach http://athome.tld/, it's equivalent to 
  HTML URL:http://athome.tld/index.php.
       You're good to use PHP for most use cases.
       
       ### Add PHP modules
       
       If you read /usr/local/share/doc/pkg-readmes as suggested by pkg_add, 
       you already know what to do πŸ˜‰. You have to add symlinks from 
   DIR /etc/php-7.9.sample to /etc/php-7.9 (edit php version).
       ```
       # cd /etc/php-7.9.sample
       # for i in *; do ln -sf ../php-7.9.sample/$i ../php-7.9/; done
       # rcctl restart php74_fpm
       ```
       
       With main php package, most extension are already installed. You may 
       add the following as they are quite common and useful :
       
       * php-curl : online requests
       * php-gd : handle images
       * php-intl : internationalization
       * php-zip : compression
       * libmcrypt : encryption
       * pear and "pecl-..."
       
       ### Edit PHP configuration
       
       Edit /etc/php-*.ini. Below is an example of some useful changes:
       
       ```
       ; Increase the size of uploadable files
       post_max_size = 10M
       upload_max_filesize = 10M
       ; let php download remote content
       allow_url_fopen = On
       ; Timezone
       date.timezone = Europe/Paris
       ```
       
       ### Configuration to deal with httpd's chroot
       
       Your php pages may need to download remote content. Therefore, it must 
       be able to do domain name resolution, check tls certificates and more. 
       The necessary is stored in /etc. However, if you remember, httpd is 
       chrooted. Do you remember where ?
       
       > In /var/www !!!
       
       Indeed Jean-Michel! Good to have you here. 😁
       
       We'll have to copy a few files usually stored in /etc to /var/www/etc:
       
       ```
       # cd /var/www     # go in the chroot 
       # mkdir etc/      # create etc directory
       # cp /etc/resolv.conf etc/resolv.conf # for Domain resolution       
       # cp /etc/hosts etc/hosts # DN too
       # cp /etc/localtime etc/localtime
       # mkdir etc/ssl   # Create another directory for tls certs
       # install -m 444 -o root -g bin /etc/ssl/cert.pem /etc/ssl/openssl.cnf \
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       ```
       
       Those files must be read only :
       
       ```
       chmod -R 444 /var/www/etc/*
       chmod -R a+X /var/www/etc/
       ```
       
       Copied files are necessary to:
       
       * /etc/resolv.conf and /etc/hosts: Do DNS name resolution.
       * /etc/localtime: Be on time
       * /etc/ssl/*: Check SSL certs. It has to be updated periodically. Add 
         in /etc/monthly.local :
       
       ```
       install -m 444 -o root -g bin /etc/ssl/cert.pem \
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       ```
       
       If you need PHP to send mails, you must copy sh in chroot (see 
   DIR /usr/local/share/doc/pkg-readmes/femail-chroot*).
       ```
       # cp /bin/sh /var/www/bin/
       ```
       
       At last, reload php πŸ˜‰.
       
       ## How to set permission on your website files ?
       
       Setting appropriate permissions on files is mandatory to keep your data 
       safe. You want to keep an eye on who can read some files or not, and 
       even more carefully on files to execute or not.
       
       For a website, there are no perfect solution, so make sure you 
       understand the following advices and make your own choices.
       
       You should set owner and group to "www" and "daemon" so httpd can read 
       the files :
       
       ```
       # chown -R www:daemon /var/www/htdocs/website
       ```
       
       For a static website (no PHP), remove execution (-x) and writing (-w) 
       permissions. You should let one change current path in these 
       directories (+X).
       
       ```
       # chmod -R a-xw /var/www/htdocs/website 
       # chmod -R ug+X /var/www/htdocs/website
       ```
       
       First, you remove x and w permissions to everyone, and then add to 
       owner and group permission to change into this directory.
       
       For a dynamic website, you need to write in the directory and execute 
       files in them :
       
       ```
       # chmod -R a-xw /var/www/htdocs/website # remove all x and w permissions
       # chmod -R u+xwX /var/www/htdocs/website # owner can xwX
       # chmod -R g+rX /var/www/htdocs/website  # group can read
       ```
       
       WARNING : you really should edit permissions more carefully to suit 
       your website case.
       
       For information, most commercial web hosters use the following 
       permissions (not saying that's the best) :
       
       * Directories : read and write for owner, read for others (755).
       * Files : owner can write in files, others can olny read (644).
       
       To apply the previous permissions :
       
       ```
       # chmod -R a-rwx /var/www/htdocs/site    # remove all perms
       # chmod -R a+rX /var/www/htdocs          # everyone can read and cd in directories
       # chmod -R u+w /var/www/htdocs           # only owner can write
       ```
       
       Notice the "X" (not "x").
       
       ## A few tips for httpd
       
       ### man httpd
       
       You should read man "httpd.conf".
  HTML URL:https://man.openbsd.org/httpd.conf
       Really.
       
       You'll find what's written here and more.
       
       ### httpd logs
       
       Choose where to store logs.
       
       By default, they are in /var/www/logs
       
       ```
       log access "website-name.log"
       ```
       
       Disable logs with "no log".
       
       ### gzip compression
       
       Add gzip-stati instruction in a domain configuration or a location 
       section. Thus, httpd try to deliver the requested file with ".gz" 
       suffix if it is present.
       
       This is good for bandwidth, it can reduce 2x to 10x the weight to 
       transfer. Compressoin ratio is good on text files (html, css, js, svg, 
       ...)
       
       To gzip a file before uploading on your server :
       
       ```
       $ gzip -vk9 index.html
       index.html:                49.5% -- replaced with index.html.gz
       1395 bytes in, 733 bytes out
       ```
       
       ### Custom error pages
       
       Add errdocs intruction to tell which directory contains custom error 
       pages. A err.html file for all errors or specific pages which filename 
       is the error code can be used.
       
       As example :
       
       ```
       errdocs "/htdocs/athome.tld/err"
       ```
       
       In /var/www/htdocs/athome.tld/err", there is the following "err.html" :
       
       ```
       <!DOCTYPE html>
       <html>
       <head>
       <meta charset="UTF-8" />
       <meta name="viewport" content="width=device-width, initial-scale=1">
       <link rel="icon" href="/favicon.png" type="image/png" />
       <style type="text/css">body, html {height:100%; margin:0}
       #bg {
           position: relative;
           background-position: center;
           background-repeat: no-repeat;
           background-size: cover;
           background-image: url("/img/errimg.jpg");
           height: 100%;
           padding:0;
           margin:0;
       }
       #content {
           padding:1.5em;
       }
       </style>
       <title>
       $RESPONSE_CODE : $HTTP_ERROR
       </title>
       </head>
       <body>
       <div id="bg">
           <div id="content">
               <h1>Error page πŸ˜–</h1>
               <p>Sorry!</p>
           </div>
       </div>
       </body>
       </html>
       ```
       
       ### Improve disponibility
       
       To increase the number of server processes and thus serve 
       simultaneously content to multiple clients, increase the default value 
       of 3 :
       
       ```
       prefork 10
       ```
       
       ### Publish in utf-8
       
       If you try to serve plain text, the web browser may have trouble to 
       display some glyphs except if you specifically set it to utf-8.
       
       To avoid clients to look for this setup, you can explicitly send the 
       appropriate header. However, the semicolon has to be escaped making the 
       configuration a bit weird. Here is an example for ".txt" and ".gmi" 
       file extensions :
       
       ```
       types {
           include "/usr/share/misc/mime.types"
               text/"plain;charset=UTF-8" gmi
               text/"plain;charset=UTF-8" txt
               text/"plain;charset=UTF-8" awk
               text/"plain;charset=UTF-8" sh
               text/"plain;charset=UTF-8" c
       }
       ```
       
       Notice how we add lines about UTF-8 after including 
   DIR /usr/share/misc/mime.types to overwrite previous declarations.
       ### Password restricted pages
       
       Create login credentials with htpasswd:
       
       ```
       # htpasswd /var/www/secret.htpw login
       ```
       
       Replace "login" with any username and set a strong password.
       
       Do it again to add more users.
       
       Set appropriate permissions on this file :
       
       ```
       # chown www /var/www/secret.htpw
       # chmod 400 /var/www/secret.htpw
       ```
       
       Finally, tell httpd to read this file for credentials and ask client to 
       enter login + password when /hidden_directory is requested :
       
       ```
       location "/hidden_directory/*" {
           authenticate "Restricted access" with "/secret.htpw"
       }
       ```
       
       secret.htpw location is relative to httpd's chroot.
       
       For a whole website :
       
       ```
       location "/*"
       ```
       
       Or add authenticate instruction at the very beginning without any 
       "location".
       
       ### httpd automatic index
       
       To display a list of files availables in a directory if no index.html 
       is found :
       
       ```
       location "/dir/*" {
           directory auto index
       }
       ```
       
       ### Include configuration files
       
       If you have many websites, you can include files in /etc/httpd.conf 
       instead of writing again and again the same thing :
       
       ```
       include "/etc/httpd/site1.conf"
       include "/etc/httpd/site2.conf"
       ```
       
       ### httpd TLS
       
       Add a "ticket session lifetime" to speed up next TLS negociation.
       
       ```
       hsts preload
       tls {
         certificate "/etc/ssl/athome.tld.crt"
         key "/etc/ssl/private/athome.tld.key"
         ticket lifetime default
       }
       ```
       
       ## Relayd and headers
       
       Because httpd can't manage headers itself, you can put relayd "before" 
       httpd.
       
       As you can guess, relayd is included in base installation.
       
       Visit this link to test your website headers.
  HTML URL:https://securityheaders.com/
       ### Relayd configuration
       
       Edit /etc/relayd.conf to configure relayd. Inside, add the following 
       lines as example to set a few headers:
       
       ```
       http protocol "http" {
         match request header remove "Proxy"
         match response header set "X-Xss-Protection" value "1; mode=block"
       
         return error
         pass
       }
       
       relay "www" {
         listen on 192.0.2.2 port 80
         protocol "http"
         forward to localhost port 8080
       }
       ```
       
       Those lines means :
       
       * http protocol "http" {: you open a new configuration section for 
         protocol http called later.
       * match request header remove "Proxy": you remove the header "Proxy" to 
         avoid httpoxy exploit.
       * match response header set "X-Xss-Protection" value "1;..." : we add a 
         header to mitigate XSS attacks
       * return error: if there is a problem, return an error
       * pass: otherwise, go on
       * relay "www" {: you add a section to redirect traffic to httpd daemomn.
       * listen on 192.0.2.2 port 80: we listen on port 80 on your public IP.
       * protocol "http: we use the previously defined protocol
       * forward to localhost port 8080: we redirect to httpd now supposed to 
         listen on localhost on port 8080 to avoid mistakes.
       
       That's why you must edit httpd configuration accordingly :
       
       ```
       # httpd's configuration
       listen on localhost port 8080
       ```
       
       To sum up, things goes like this now :
       
       * 1. A client ask to see your website and knocks at port 80.
       * 2. relayd modify a few headers and redirect to httpd which still 
         serve the website.
       
       Dont forget to reload relayd and httpd:
       
       ```
       # rcctl enable relayd
       # rcctl restart httpd
       # rcctl start relayd
       ```
       
       Notice logs will show incoming connections from 127.0.0.1 (relayd local 
       address). You may want to use forwarded log format for httpd in 
   DIR /etc/httpd.conf, so the incoming IP source is appended:
       ```
       log style forwarded
       ```
       
       ### relayd and TLS / https
       
       Find below an example to add TLS support to relayd. There are a few 
       things to take care of about certificates and keys.
       
       ```
       http protocol "https" {
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       mode=block"
       
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       }
       
       relay "tlsforward" {
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       Happy helping β˜ƒ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day!
       }
       ```
       
       Look at the lines starting with tls keypair. They define the 
       certificate and keys to use for TLS. In the above example, two 
       certificates for two different domains are used, you can add as much as 
       you have certificates to use.
       
       However, those certificates MUST be stored with the appropriate 
       filename in the correct location :
       
       ```
       [9|[9|```|/etc/ssl/athome.tld.crt|server|port]
       Make sure /etc/ssl/athome.tld.crt is the "full chain certificate".
       
       This means you should have such configuration in acme-client 
       configuration :
       
       ```
       domain athome.tld {
           domain key "/etc/ssl/private/athome.tld.key"
           domain certificate "/etc/ssl/athome.tld-cert.crt"
           domain chain certificate "/etc/ssl/athome.tld-chain.crt"
           domain full chain certificate "/etc/ssl/athome.tld.crt"
           sign with letsencrypt
       }
       ```
       
       This way, relayd will automatically pick up the right certificate.
       Notice you can now remove all tls configuration from httpd, relayd 
       handle it.
       
       ### relayd and certificates renewal
       
       Remember to reload relayd after certificate renewal :
       
       ```
       [1|/usr/sbin/rcctl reload relayd ```|/usr/sbin/acme-client -v athome.tld && \|server|port]
       ### Relayd and IPv6
       
       If you want to add ipv6 support with relayd, it is obviously possible.
       
       First, make sure you set the local address in /etc/hosts :
       
       ```
       127.0.0.1 localhost
       ::1 localhost
       ```
       
       You can now use localhost to refer to both ipv4 or ipv6 local depending 
       on context.
       
       Now add two entries in relayd configuration:
       
       ```
       relay "http" {
               listen on $ext_ip4 port 80
               protocol "http"
               forward to 127.0.0.1 port 80
       }
       
       relay "http6" {
               listen on $ext_ip6 port 80
               protocol "http"
               forward to ::1 port 80
       }
       ```
       
       httpd's configuration will make use of localhost so it's simpler :
       
       ```
       listen on localhost port 80
       ```
       
       ### Relayd and security headers
       
       You can set a few headers to improve your website security. It's mostly 
       useful if you host huge webapps, not really for static websites.
       
       ```
       match request header remove "Proxy"
       match response header set "Frame-Options" value "SAMEORIGIN"
       match response header set "X-Xss-Protection" value "1; mode=block"
       match response header set "X-Frame-Options" value "SAMEORIGIN"
       match response header set "X-Robots-Tag" value "index,nofollow"
       match response header set "X-Permitted-Cross-Domain-Policies" value "none"
       match response header set "X-Download-Options" value "noopen"
       match response header set "X-Content-Type-Options" value "nosniff"
       match response header set "Permissions-Policy" value "interest-cohort=()"
       # HSTS Equivalent:
       match response header set "Strict-Transport-Security" value "max-age=31536000; includeSubDomains"
       # only load resources from ourselves
       match response header set "Content-Security-Policy" value "default-src 'self';"
       ```
       
       If you only host one domain, add :
       
       ```
       match response header set "Access-Control-Allow-Origin" value "athome.tld"
       ```
       
  HTML Learn more about Access-Control-Allow-Origin header
       ### Optimize client cache and bandwidth usage
       
       You should consider to tune up the amount of request a client should 
       make each time it checks on your website. As example, you can specify 
       to keep in cache files such as pictures, stylesheets or fonts for a few 
       days before asking again.
       
       In "protocol" section, just before "pass" keyword, add :
       
       ```
       match request path "/*.css" tag "CACHE"
       match request path "/*.js" tag "CACHE"
       match request path "/*.atom" tag "CACHE"
       match request path "/*.rss" tag "CACHE"
       match request path "/*.xml" tag "CACHE"
       match request path "/*.jpg" tag "CACHE"
       match request path "/*.png" tag "CACHE"
       match request path "/*.svg" tag "CACHE"
       match request path "/*.gif" tag "CACHE"
       match request path "/*.ico" tag "CACHE"
       
       match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400"
       ```
       
       Everytime a client ask for a file ending with ".css" or ".js" or 
       ".atom" (...), relayd tag the resquest with "CACHE". At last we add a 
       header to increase cache to 21 days to requests with this tag.
       
       ### Set default encoding
       
       Following the same scheme, you can specify the default encoding 
       according to file extension :
       
       ```
       match request path "/*.html" tag "UTF8"
       match request path "*/" tag "UTF8"
       match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"
       ```
       
       ### About relayd tags
       
       Understand you can't set multiple tags at once. If you want to apply 
       the two above headers (cache-control and content-type), you must do it 
       separately since relayd configuration is processed in order :
       
       ```
       match request path "/*.html" tag "CACHE"
       match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400"
       
       match request path "/*.html" tag "UTF8"
       match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"
       ```
       
       ## Databases
       
       Databases are essentials to organize data linked to each others.
       
       As example, a blog engine needs to know who commented which article, at 
       which date and by whom. This comment has a link, the author may have 
       left a mail address to get an alert when there is an answer... All 
       those are tied together.
       
       When you self host, you may not need a huge database engine. In this 
       scenario, I recommend SQLite: easy to backup and light even if there 
       are less features you won't use anyway.
       
       ### SQlite
       
       SQlite is amazing.
  HTML URL:https://www.sqlite.org/
       It is easy and light. To backup, just copy a file. It is more than 
       enough in mosts cases.
       
       To install, just :
       
       ```
       # pkg_add sqlite3.
       ```
       
       To use with PHP, add php-pdo_sqlite-* and php-sqlite3-*.
       
       To backup the database, just copy the database file. That's it 😊.
       
       ### MariaDB (MySQL)
       
       Very well known database engine, MySQL or MariaDB is often required in 
       webapps. Make sure to understand how to secure your installation as it 
       is a sensitive software.
       
       Read /usr/local/share/doc/pkg_readmes/* related to mariadb install.
       
       To use with PHP, install php-mysqli-* and php-pdo_mysql-* then enable 
       extensions as explained in PHP's part.
       
       To install MariaDB :
       
       ```
       # pkg_add mariadb-server
       # /usr/local/bin/mysql_install_db
       ```
       
       The second command install a default database.
       
       To start mysql :
       
       ```
       # rcctl enable mysqld
       # rcctl start mysqld
       ```
       
       Finally, use the following command to improve mysql safety :
       
       ```
       # /usr/local/bin/mysql_secure_installation
       ```
       
       To let httpd talk with MariaDB (it is chrooted), enter those commands 
       to reproduce root structure with appropriate permissions :
       
       ```
       # install -d -m 0711 -o _mysql -g _mysql /var/www/var/run/mysql
       ```
       
       Add those lines to /etc/my.cnf to change MariaDB socket location so it 
       is accessible to httpd :
       
       ```
       [client]
           socket = /var/www/var/run/mysql/mysql.sock
       
       [mysqld]
           socket = /var/www/var/run/mysql/mysql.sock
       ```
       
       At last, restart mysql :
       
       ```
       # rcctl restart mysqld
       ```
       
       Now you can add users and databases.
       
       As example, we will show how to create a database for Wordpress.
       
       Enter "# mysql -u root -p" To get to the MariaDB shell. Below see a log 
       of inputs and ouputs.
       
       ```
       # mysql -u root -p
       Enter password:
       Welcome to the MariaDB monitor.  Commands end with ; or \g.
       Your MariaDB connection id is 3
       Server version: 10.0.23-MariaDB-log openBSD port: 
       mariadb-server-10.0.23p0v1
       
       Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
       
       Type 'help;' or '\h' for help. Type '\c' to clear the current input 
       statement.
       
       MariaDB [(none)]> CREATE DATABASE wordpress_base;
       Query OK, 1 row affected (0.01 sec)
       
       MariaDB [(none)]> CREATE USER 'wp'@'localhost' IDENTIFIED BY 'password';
       Query OK, 0 rows affected (0.01 sec)
       
       MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress_base.* TO 
       'wp'@'localhost';
       Query OK, 0 rows affected (0.00 sec)
       
       MariaDB [(none)]> FLUSH PRIVILEGES;
       Query OK, 0 rows affected (0.00 sec)
       
       MariaDB [(none)]> exit
       Bye
       ```
       
       That's it 😊.
       
       To get backup a MariaDB base (a dump) to db-name:
       
       ```
       # mysqldump -u root -p db-name > /var/backup/db_backup
       ```
       
       Of course, edit user root and db-name.
       
       To restore the database :
       
       * 1. Delete old db.
       * 2. Recreate the base, but empty.
       * 3. Import the previous dump.
       
       ```
       # mysql -u root -p -e "DROP DATABASE db-name
       # mysql -u user -e "CREATE DATABASE db-name
       # mysql -u user -p db-name < /var/backup/db-backup
       ```
       
       Notice the "<" backwards.
       
       ### PostgreSQL
       
       PostgreSQL is another database engine. Install postgresql-server port 
       to use it.
       
       With PHP, you'll need php-pgsql-* and php-pdo_pgsql-* too.
       
       Read /usr/local/share/doc/pkg-readmes/postgresql* carefully πŸ˜‰.
       
       Create a default database :
       
       ```
       # su - _postgresql
       $ mkdir /var/postgresql/data
       $ initdb -D /var/postgresql/data -U postgres -A scram-sha-256 -E UTF8 -W
       $ exit
       ```
       
       Default user is postgres.
       
       Edit /var/postgresql/data/postgresql.conf to suit your needs.
       
       To let httpd access postgresql, you should have :
       
       ```
       unix_socket_directories = '/var/www/tmp/postgresql, /tmp'
       ```
       
       You have to edit permissions on this directory :
       
       ```
       # mkdir -p /var/www/tmp/postgresql
       # chown _postgresql:www /var/www/tmp/postgresql
       ```
       
       To start postgresql, as usual :
       
       ```
       # rcctl enable postgresql
       # rcctl start postgresql
       ```
       
       To get the postgresql shell :
       
       ```
       # su _postgresql -c psql
       ```
       
       Below a few examples to dael with postgresql :
       
       Change admin password :
       
       ```
       # psql -U postgres -c "ALTER USER postgres WITH PASSWORD 
       'new_password'";
       ```
       
       Add "toto" user :
       
       ```
       # psql -U postgres -c "CREATE USER toto WITH PASSWORD 'password';"
       ```
       
       Create a new database and let toto do everything he wants with :
       
       ```
       # psql -U postgres 
       \connect template1
       CREATE DATABASE "new_db" WITH ENCODING 'UTF-8';
       GRANT ALL PRIVILEGES ON DATABASE "new_db" TO toto;
       ALTER DATABASE "new_db" OWNER TO toto;
       \q
       ```
       
       To save a database with postgresql, you actually save all the 
       instructions to recreate the database :
       
       ```
       # pg_dump db-name > /var/backup.db
       ```
       
       To restore the base :
       
       ```
       # psql -U postgres db-name < /var/backup.db
       ```
       
       ## Webapps you can host
       
       There are numbers of webapps : Wikis, Blogs, CMS, Webmails...
       
       Most of the time, you'll need PHP and sometimes a database engine to 
       run them.
       
       ! Make sure to check official documentation related to each webapps. ! 
       Also check release notes as long as you host these apps to keeps your 
       install secure. It is a good idea to subscribe to RSS feed or mailing 
       lists of projects you host.
       
       Most of the time, the steps to install a webapp are the same.
       
       * 1. Make a new directory dedicated to the app in /var/www/htdocs ;
       * 2. Download and uncompress an archive of the application ;
       * 3. Move files in the previous directory ;
       * 4. Adjust permissions on the new files : # chown -R www:daemon 
         /var/www/htdocs/thesite. Fine tune this part, of course.
       * 5. Edit /etc/httpd.conf following related documentation or looking in 
         an eventual htaccess file to restrict some accesses ;
       * 6. If necessary, increase upload size limit for httpd and PHP.
       * 7. Reload httpd then end the install with a browser opened on your 
         new website.
       
       ### Nice webapps selection
       
       There are so many webapps you may ask yourselves which one you should 
       consider. Below I suggest a few of them with a few requirements :
       
       * Priority is given to tools already packaged for OpenBSD so you can 
         enjoy tweaks from OpenBSD developpers. Thus, it is more secure and 
         already well integrated.
       * They must be as light as possible : if you self-host, you may not 
         have very powerful hardware.
       * They should be easy to install or administer. That's why we avoid 
         complex databases and prefer SQLite.
       
  HTML Nextcloud.
       As the name suggest, it is a cloud (and many app).
       
       Just "# pkg_add nextcloud", then
       read /usr/local/share/doc/pkg-readme/nextcloud. 😁
       
  HTML Dokuwiki.
       Just "# pkg_add dokuwiki", then 
       read /usr/local/share/doc/pkg-readme/dokuwiki.
       
       It is not only a wiki, and can be used as a blog engine or a CMS.
       It's quite an amazing tool. 
       
       Also, read : 
       
  HTML dokuwiki notes about security.
  HTML How to setup dokuwiki on OpenBSD.
  HTML SnappyMail.
       It is easy to install as you can read a bit further.
       
  HTML Roundcube is packaged for OpenBSD even though it's harder to  administer.
  HTML Squirrelmail is old but I strongly recommend it since it is well tested  and works very well as a webmail.
  TEXT See my own configuration example here.
  HTML PluXML : light blog engine, no database, full of functionnality.
  HTML PureBlog : A simple PHP based blogging platform.
  HTML Kriss Feeds (just 1 file πŸ˜‰):
  HTML FreshRSS (available in ports tree);
       ### Where can I find other apps to host ?
       
  HTML Look on alternativeto.
  HTML This github selection is well filled.
       ### Webmail attachments or file upload size limit
       
       Attachments size are 35M by default with smtpd mail server, that's why 
       you should edit /etc/php-*.ini configuration :
       
       ```
       post_max_size = 35M
       upload_max_filesize = 35M
       ```
       
       You have to set this limit in httpd's configuration too :
       
       ```
       connection max request body 36700160
       ```
       
       ---
       
   DIR Table of contents
       [1|