diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2025-07-01 17:01:45 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2025-07-01 17:01:45 +0900 |
| commit | 516f632b84bc418486538a2183564fe94b89097e (patch) | |
| tree | 56fed110e820d6520b39e550ccca31f00cae33ff | |
init
219 files changed, 15504 insertions, 0 deletions
diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.hugo_build.lock diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <https://unlicense.org> diff --git a/README.md b/README.md new file mode 100644 index 0000000..e469d5c --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# SiCh ([https://chad.thesiah.xyz](https://chad.thesiah.xyz)) + +A site dedicated to turn web peasants into Internet SiCh. + +Simple step-by-step text and image-based tutorials for creating websites, email servers, chat servers, server administration and everything else. + +Suggestions welcome. + +This site is compiled and organized with Hugo, using [this very simple theme](https://github.com/TheSiahxyz/lugo). + +## Submission guidelines + +- Guides should be made for the most recent stable version of Debian. (Now Debian 12.) +- Follow the general style of pre-existing articles. +- use the root user (i.e. no `sudo`) unless there is a specific need. +- do not preface commands with `$` or `#` or anything. +- use `.svg` files for icons/logos and for illustrative images favor webp, keep filesize low. +- Use `example.org` the example domain. +- Do not add Docker tutorials. +- Installable services must have the `service` tag and an `icon` set in the metadata so they properly appear in the service display. +- Server/sysadmin tips should have the `server` tag, so they appear in that list. + +## License + +Adding anything to this site puts it in the public domain. You are welcome to add your personal links to the bottom of pages you write for credit. diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..46bfb31 --- /dev/null +++ b/config.toml @@ -0,0 +1,9 @@ +baseURL = 'https://chad.thesiah.xyz' +languageCode = 'en-us' +title = 'Sich' +theme = 'lugo' + +[markup] + [markup.goldmark] + [markup.goldmark.renderer] + unsafe = true diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..2043545 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,67 @@ +--- +title: "SiCh" +layout: single +--- + +This is SiCh, a site dedicated to turning internet peasants into Internet Landlords by showing them how to setup websites, email servers, chat servers and everything in between. + +Starting a website is something that can be done in a lazy afternoon and costs pocket change. + +Most of the internet's problems could be solved if more people had their own personal platforms, so the objective of this site is to guide any normal person through the process of installing a website. + +## Start a website + +<div> + +<div class=left> + +This is the basic "course." Follow these quick tutorials and you'll have a fully functioning basic web page on the domain name of your choice. + +⏳ This "basic course" can take **as little as an hour** or even less. + +</div> + +<div class=right> + +{{< basic >}} + +</div> +<br> +</div> + +## "Build your own platform!" + +{{< services >}} + +Host your own services, social media and more. + +## Setup an Email Server + +<div> + +<div class=left> + +This is the email "course". Follow these modules to learn how to setup an email server headache free. + +⏳ This entire "email course" may take **about an hour**. The approval for opening email ports with your VPS should take **no less than a day**. + +</div> + +<div class=right> + +{{< mail >}} + +</div> +<br> +</div> + +## Maintaining a Server + +Tips and articles on mastering your server and learning about GNU/Linux systems administration. + +{{< maintain >}} + +## Support SiCh + +- BTC: `bc1q9f3tmkhnxj8gduytdktlcw8yrnx3g028nzzsc5` +- XMR: `84RXmrsE7ffCe1ADprxLMHRpmyhZuWYScDR4YghE8pFRFSyLtiZFYwD6EPijVzD3aZiEpg57MfHEr1pGJNPXyJgENMnWrSh` diff --git a/content/alps.md b/content/alps.md new file mode 100644 index 0000000..98fb9c1 --- /dev/null +++ b/content/alps.md @@ -0,0 +1,99 @@ +--- +title: "Alps" +tags: ["service"] +icon: "alps.webp" +short_desc: "Alps is a simple and extensible webmail. It offers a web interface for IMAP, SMTP and other upstream servers." +date: 2024-07-16 +--- + +[Alps](https://git.sr.ht/~migadu/alps) +is a webmail client, a program that allows you to access your email +online like Gmail. It is useful to be able to access you email from a +web browser because it allows you to easily access your email from any +device with a web browser without much additional setup. + +## Instructions + +There is no Debian package so we are going to build it from source. You need to +have a newer Go compiler installed than what is in the Debian repos. You can +follow the [instructions +here](https://www.vultr.com/docs/install-the-latest-version-of-golang-on-Debian/) +to install Go. + +Then, we can clone and build alps. + +```sh +git clone https://git.sr.ht/~migadu/alps /opt/alps +cd /opt/alps +go build ./cmd/alps +mv alps /usr/local/bin/alps +``` + +Now, we are going to create a login key with this command. + +```sh +go run github.com/fernet/fernet-go/cmd/fernet-keygen +``` + +Now, we need to create a systemd service to auto start it on boot. + +```systemd +[Unit] +Description=Alps Webmail +After=network.target +Wants=network-online.target + +[Service] +Restart=always +Type=simple +ExecStart=/usr/local/bin/alps -theme alps -addr 127.0.0.1:1323 -login-key yourloginkey imaps://mail.example.org:993 smtps://mail.example.org:465 +WorkingDirectory=/opt/alps +Environment="GOPATH=/opt/alps/.gopath" +Environment="GOCACHE=/opt/alps/.gocache" + +[Install] +WantedBy=multi-user.target +``` + +If you run Postfix and Dovecot on the same machine, you could change the `After` string to the following:Add commentMore actions + +``` +After=network.target postfix.service dovecot.service +``` + +Put that in `/etc/systemd/system/alps.service` and fill in your login key and your mail domain. + +Now, reload and start Alps. + +```sh +systemctl daemon-reload +systemctl enable --now alps +``` + +You will need to have already set up nginx. Add this to a file in `/etc/nginx/sites-available/alps.conf`. + +```nginx +server { + listen 80; + + server_name mail.example.com; + + location / { + proxy_pass http://localhost:1323; + } +} +``` + +Now, link it to `/etc/nginx/sites-enabled/alps.conf` with this command. + +```sh +ln -s /etc/nginx/sites-available/alps.conf /etc/nginx/sites-enabled/alps.conf +``` + +Now, run `certbot` and select your new domain to setup ssl on it. + +Finally, you can access your web mail at `mail.example.org` and log in with your email and password. + +## Contribution + +XMR: `86MMzQFTWgWHdLmJgdUSyKYKitVtgw3Dbfe2hTFeZmSC92FUE7wFcEF5AA4ugqyge4hGdL8PwvZKB49fsGLbUtYdGmNgNU9` diff --git a/content/auth.md b/content/auth.md new file mode 100644 index 0000000..b38cb88 --- /dev/null +++ b/content/auth.md @@ -0,0 +1,134 @@ +--- +title: "Requiring Passwords for Webpages (HTTP Authentication)" +date: 2020-07-01 +img: 'auth.svg' +tags: ['server'] +--- + +HTTP basic authentication will allow you to secure parts (or all) of +your website with a username and password without the trouble of PHP or +Javascript. This will work with any Nginx server. + +## Installation + +We will be using the command `htpasswd` to make username and password +pairs. + +```sh +apt install apache2-utils +``` + +The apache utils include a small username-password pair encryption tool. + +Like the other tutorials on this site, this tutorial is for Nginx, +**not** for Apache servers. + +Now think of a username and password and remember them. + + htpasswd -c /etc/nginx/myusers username + +The `-c` flag creates a file. You can make the path of this file +anywhere outside of your webroot. + +Obviously the username is up to you as well. + +Type out your password twice to confirm. You can do this as many times +as you\'d like. + +Check out user name password pairs (the password will be securely +hashed): + + cat /etc/nginx/myusers + +## Nginx Config and Auth Basic + +From here, we are going to edit our websites config file in +`/etc/nginx/sites-enabled`. Have in mind which folder you\'d like to +secure. Add something like this: + +```nginx +server { + #... + location /secret-folder { + auth_basic "What's the Password?" ; + auth_basic_user_file /etc/nginx/myusers ; + } + #... +} +``` + +#### Huh? + +If you\'re stuck, try finding the line `location / {` + +Just below this block is where you should add the custom location block + +If you\'d like to do the opposite, such as making the entire site +private except for a public section, do this: + +```nginx +server { + #... + auth_basic "What's the Password?" ; + auth_basic_user_file /etc/nginx/myusers ; + location /public/ { + #... + auth_basic off ; + } + #... +} +``` + +### IP Addresses + +If passwords aren\'t enough we can ban an ip or accept one. + +```nginx +location /api { + #... + allow 192.168.1.23:8080 ; + deny 127.0.0.1 ; +} +``` + +If you want to check both a username and password with an ip address, +use the `satisfy` directive. + +```nginx +location /api { + #... + satisfy all ; + + allow 192.168.1.23:8080 ; + deny 127.0.0.1 ; + + auth_basic "What's the Password?" ; + auth_basic_user_file /etc/nginx/myusers ; +} +``` + +### Complete Example + +```nginx +http { + server { + listen 80; + root /var/www/website ; + + #... + location /secret-folder { + satisfy all ; + + allow 192.168.1.3/24; + deny 127.0.0.1 ; + + auth_basic "What's the Password?" ; + auth_basic_user_file /etc/nginx/myusers ; + } + } +} +``` + +Now check your configuration with `nginx -t` + +Reload nginx and you\'re good to go! diff --git a/content/bandwidth.md b/content/bandwidth.md new file mode 100644 index 0000000..2313524 --- /dev/null +++ b/content/bandwidth.md @@ -0,0 +1,88 @@ +--- +title: "Loading Fast and Saving Bandwidth" +draft: true +--- +## Images + +Image files will usually have the most impact on the speed of your +websites (aside from Ad/tracker scripts). Learn to slim down your images +using the ubiquitous *ImageMagick* to make your websites faster on slow +internet connections. + + + +There are some rules of thumb to keep in mind with images: + +1. Only use images as large as you need on the webpage. +2. Use the proper containers. E.g. a photograph should never be a + `.png`, but a `.jpg`, or even better, a `.webp`. +3. Where it will not be visible, reduce image quality. + +### webp vs. png vs. svg + +`png` images are best for accurately recording images **without color +gradients**. A `png` photograph will be massive in size, but a `png` +cartoon without color + +#### An imagemagick experiment + +We can illustrate this difference with imagemagick. Run the following +two commands. They will create two png files containing nothing by the +color red. The first will create a 100x100 pixel image, and the second +will create a massive 10,000x10,000 image. (The second command will take +a few seconds to finish.) + + magick -size 100x100 canvas:red red-small.png + magick -size 10000x10000 canvas:red red-large.png + +Once we\'ve done that, let\'s rerun the same commands, except for let\'s +output them into `jpg` containers: + + magick -size 100x100 canvas:red red-small.jpg + magick -size 10000x10000 canvas:red red-large.jpg + +Once we\'ve run all those commands, you will see that `red-large.jpg` is +a massive 1.2M, while `red-large.png`, despite still being 10,000 square +pixels like the jpg, is a mere 13K in filesize. + +------------------------------------------------------------------------ + +For the examples, I decided to use +[this](https://commons.wikimedia.org/wiki/File:Tabby_cat_with_blue_eyes-3336579.jpg) +public domain image. + +{style="width: 50%;"} + +There are many ways to decrease image size using ImageMagick, the +simplest is to use the `-quality` option, which will compress the image +without changing the resolution. This option takes the value you want to +compress by (between 1 and 100, the lower the value, the lower the file +size). For example: + + convert in.jpg -quality 50 out.jpg + +Compressing the example image above results in the following file size +changes: + + Quality Size + ---------- ------ + Original 2.1M + 90 1.7M + 80 844K + 70 588K + 60 448K + 50 368K + 40 308K + 30 248K + 20 184K + 10 116K + +Due to the images high resolution, it is usable in this website even +when highly compressed (30% quality, still looks decent in my opinion). + +## Contribution + +- [Musse](https://na20a.neocities.org/) +- Monero: + `83is3y69Xv4fkFsTpZhw5c3bfxtimupfgTdpERHM1WtMNAwSqFjTCJm3VabyBKXKnL873dWPmqj4bRcgkm9oCktgQrzmhHd`{.crypto} diff --git a/content/basic/certbot.md b/content/basic/certbot.md new file mode 100644 index 0000000..f85c4db --- /dev/null +++ b/content/basic/certbot.md @@ -0,0 +1,132 @@ +--- +title: "Certbot and HTTPS" +date: 2021-07-13 +tags: ['basic'] +--- +Once you have a website, it is extremely important to enable encrypted +connections over HTTPS/SSL. You might have no idea what that means, but +it\'s easy to do now that we\'ve [set our web server up](/basic/nginx/). + +Certbot is a program that automatically creates and deploys the +certificates that allow encrypted connections. It used to be painful +(and often expensive) to do this, but now it\'s all free and automatic. + +## Why is encryption important? + +- With HTTPS, users\' ISPs cannot snoop on what they are looking at on + your website. They know that they have connected, but the particular + pages they visit are private as everything is encrypted. HTTPS + increases user privacy. +- If you later create usernames and passwords for any service on your + site, lack of encryption can compromise that private data! Most + well-designed software will automatically *prevent* any unencrypted + connections over the internet. +- Search engines like Google favor pages with HTTPS over unencrypted + HTTP. +- You get the official-looking green 🔒 symbol in the URL bar in most + browsers which makes normies subtly trust your site more. + +## Let\'s do it! + +{{< img alt="website without https/ssl" src="/pix/nginx-website.png" link="/pix/nginx-website.png" >}} + +Note in this picture that a browser accessing your site will say \"Not +secure\" or something else to notify you that we are using an +unencrypted HTTP connection rather than an encrypted HTTPS one. + +## Installation + +Just run: + +```sh +apt install python3-certbot-nginx +``` + +And this will install `certbot` and its module for `nginx`. + +## Run + +As I mentioned in the previous article, firewalls might interfere with +certbot, so you will want to either disable your firewall or at least +ensure that it allows connections on ports 80 and 443: + +```sh +ufw allow 80 +ufw allow 443 +``` + +Now let\'s run certbot: + +```sh +certbot --nginx +``` + +The command will ask you for your email. This is so when the +certificates need to be renewed in three months, you will get an email +about it. You can set the certificates to renew automatically, but it\'s +a good idea to check it the first time to ensure it renewed properly. +You can avoid giving your email by running the command with the +`--register-unsafely-without-email` option as well. + +Agree to the terms, and optionally consent to give your email to the EFF +(I recommend against this obviously). + +Once all that is done, it will ask you what domains you want a +certificate for. You can just press enter to select all. + +{{< img alt="activate HTTPS for a site with certbot" src="/pix/certbot-01.png" link="/pix/certbot-01.png" >}} + +It will take a moment to create the certificate, but afterwards, you +will be asked if you want to automatically redirect all connections to +be encrypted. Since this is preferable, choose 2 to Redirect. + +{{< img alt="redirecting http to encrypted https with certbot" src="/pix/certbot-02.png" link="/pix/certbot-02.png" >}} + +### Checking for success + +You should now be able to go to your website and see that there is a +🔒 lock icon or some other notification that you are now on an encrypted +connection. + +{{< img alt="A 🔒 symbol symbolizing our new HTTPS layer for our website!" src="/pix/certbot-03.png" link="/pix/certbot-03.png" >}} + +## Setting up certificate renewal + +As I mentioned in passing, the Certbot certificates last for 3 months. +To renew certificates, you just have to run `certbot --nginx renew` and +it will renew any certificates close to expiry. + +Of course, you don\'t want to have to remember to log in to renew them +every three months, so it\'s easy to tell the server to automatically +run this command. We will use a [cronjob](/cron) for this. Run the +following command: + +```sh +crontab -e +``` + +There might be a little menu that pops up asking what text editor you +prefer when you run this command. If you don\'t know how to use vim, +choose `nano`, the first option. + +This `crontab` command will open up a file for editing. A crontab is a +list of commands that your operating system will run automatically at +certain times. We are going to tell it to automatically try to renew our +certificates every month so we never have to. + +Create a new line at the end of the file and add this content: + +```txt +0 0 1 * * certbot --nginx renew +``` + +Save the file and exit to activate this cronjob. + +For more on cron and crontabs please [click here!](/cron) + +You now have a live website on the internet. You can add to it what you +wish. + +As you add content to your site, there are many other things you can +also install linked on [the main page](/), and many more +improvements, tweaks and bonuses. diff --git a/content/basic/dns.md b/content/basic/dns.md new file mode 100644 index 0000000..c281fff --- /dev/null +++ b/content/basic/dns.md @@ -0,0 +1,95 @@ +--- +title: "Connect Your Domain and Server with DNS Records" +date: 2021-07-07 +tags: ["basic"] +--- + +## The Gist + +Now that we have a [domain](/basic/domain) and a [server](/basic/server), we +can connect the two using DNS records. DNS (domain name system) records +are usually put into your registrar and direct people looking up your +website to the server where your website and other things will be. + +Get your IPv4/IPv6 addresses from your VPS provider and put them into A/AAAA +records on your registrar. Simple process, takes a minute, but here\'s a guide +with a million images just so you know. + +## Open up your Registrar + +As before, we will be using any registrar of your choice and +[Vultr](https://www.vultr.com/?ref=8384069-6G) as a server host. Go ahead and +log into your accounts on both. Open up your registrar, or your registrar, and +click on your domain and then a choice for \"DNS records.\" You'll want to see +something like this on your registrar's site. + +{{< img alt="Blank records" src="/pix/dns-epik.png" link="/pix/dns-epik.png" >}} + +Note that we are on the \"External Hosts (A, AAAA)\" tab by default. There may +be default settings set by your registrar. If there are, you can go ahead and +delete them so they look clean like the picture above. + +**All we have to do now is get our IP addresses from Vultr and add new +DNS records that will send connections to our server.** + +Keep the registrar tab open and open Vultr and we will copy-and-paste our IP +addresses in. + +## Find your server\'s IP addresses + +Looking at your server in the Vultr menu, you should see a number next +to it. Mine here is `104.238.126.105` as you can see below the server +name (which I have named `chad.thesiah.xyz` after the domain I will soon +attach to it). That is my **IPv4** address. + +{{< img src="/pix/dns-ipv4.png" alt="See the IPv4 address?" link="/pix/dns-ipv4.png" >}} + +Copy your IPv4 address and on your registrar's site, click the \"Add Record\" +record button and add two A entries pasting in your IPv4 address like I\'ve +done for mine here. + +{{< img src="/pix/dns-ipv4-done.png" alt="IPv4 complete" link="/pix/dns-ipv4-done.png" >}} + +I add two entries. One has nothing written in the \"Host\" section. This +will direct connections to `chad.thesiah.xyz` over IPv4 to our IP address. +The second has a `*` in the \"Host\" section. This will direct +connections to all possible subdomains to the right place too, I mean +`mail.thesiah.xyz` or `blog.thesiah.xyz` and any other subdomain we +might want to add later. + +Now let\'s get our IPv6 address, which is a little more hidden for some +reason. IPv6 is important because we are running out of IPv4 addresses, +so it is highly important to allow connections via IPv6 as it will be +standard in the future. Anyway, now back on Vultr, click on the server +name. + +On the server settings, **click on settings** and we will see we are on +a submenu labeled \"IPv4\" where we see our IPv4 address again. + +{{< img src="/pix/dns-vultr.png" alt="Looking for the IPv6" link="/pix/dns-vultr.png" >}} + +Now just click on the **IPv6** submenu to reveal your IPv6 address. + +{{< img alt="The IPv6 address" src="/pix/dns-ipv6.png" link="/pix/dns-ipv6.png" >}} + +That ugly looking sequence of numbers and letters with colons in between +(`2001:19f0:5:ccc:5400:03ff:fe58:324a`) is my **IPv6** address. Yours will look +something like it. Now let\'s put it into your registrar's site. This time, be +sure to select to put in AAAA records as below: + +{{< img src="/pix/dns-ipv6-done.png" alt="IPv6 complete" link="/pix/dns-ipv6-done.png" >}} + +Now just click \"Save Changes.\" It might take a minute for the DNS +settings to propagate across the internet. + +## Test it out! + +Now we should have our domain name directing to our new server. We can +check by pinging our domain name, check this out: + +{{< img src="/pix/dns-ping.png" alt="Pinging chat.thesiah.xyz" link="/pix/dns-ping.png" >}} + +As you can see, our ping to `chad.thesiah.xyz` is now being directed to +`104.238.128.105`. That means we have successfully set up our DNS +records! You can also run the command `host` if you have it, which will +list both IPv4 and IPv6 addresses for a domain name. diff --git a/content/basic/domain.md b/content/basic/domain.md new file mode 100644 index 0000000..6a04b9c --- /dev/null +++ b/content/basic/domain.md @@ -0,0 +1,83 @@ +--- +title: "Get a Domain Name" +tags: ["basic"] +date: 2021-06-01 +--- + +## Terms + +Domain name +: The name of a website that you type in an address bar. This site\'s +domain name is `chad.thesiah.xyz`. + +Top-level domain (TLD) +: The extension of a domain name, like `.com`, `.net`, `.xyz`, etc. + +Registrar +: A service authorized to reserve a domain name for you. + +When domain names first sell, they usually sell for very cheap, but once +someone buys one, they have the rights to it until they decide to sell +it, often for much, much more money. Therefore, it\'s a good idea to +reserve a domain name ASAP, even if you didn\'t intend on doing anything +big with it. + +So let\'s register your domain name! + +## How + +Domains can be registered at any accredited <dfn>registrar</dfn> and there are +[a lot to choose from](https://www.icann.org/en/accredited-registrars). Some major names are +[Host Gator](https://www.hostgator.com/domains), +[Blue Host](https://www.bluehost.com/domains), +[Name Cheap](https://www.namecheap.com/domains/) or +[Dream Host](https://www.dreamhost.com/domains/). + +There are also sites that are more private, like [Njalla](https://njal.la/) and +[Cheap Privacy](https://cheapprivacy.ru/), which register a domain for you +under their name, but still allow you access to it. (Normally all websites must +be registered with the ICANN with a real name and address, but these sites +allow you to bypass that.) + +Choosing a registrar is not permanent, and you can transfer domains to a +different registrar if you get a better deal later, so in most cases, you can just +choose one and let's head on... + +### Basic info about domain names + +- Domain names usually require a _very_ small yearly fee to keep + registered, usually around \$12 for most generic TLDs. There are + some \"specialty\" TLDs that are more expensive, but `.com`, `.xyz` + and other basic TLDs are that cheap. +- Once you own a domain, it is yours as long as you pay the yearly + fee, but you can also sell it to someone for however much you want. +- Domain names do not hold your data or your website; instead, you add + \"DNS settings\" that direct people connecting to your domain to + your IP address. The purpose of a domain name is so that people + don\'t have to remember your IP address to find your website! + +### Looking for domain names + +Let\'s go to our registrar's site and you can search for domain names. + +You can look for whatever domain name you want. Domains that are already +bought and owned by someone else might have the option to \"Backorder,\" +but it\'s always best to get one that is unowned, like these: + +{{< img alt="Searching for a domain name" src="/pix/domain-search.png" link="/pix/domain-search.png" >}} + +Note the differences in prices. Some \"specialty\" TLDs like `.game` and +`.io` charge a much larger fee, although you might want one. Some +domains above, like `.xyz` and `.org` have reduced prices for the first +year. + +Choose the domain you want and buy it. These `.xyz` domains are a steal +now on sale. + +{{< img alt="Buying a domain name" src="/pix/domain-cart.png" link="/pix/domain-cart.png" >}} + +That\'s all you have to do to own a domain name! As you register a +domain, you can also setup an automatic payment to pay your fee yearly +to keep your domain. Easy as pie. + +Now we will get a server to host your website on. diff --git a/content/basic/nginx.md b/content/basic/nginx.md new file mode 100644 index 0000000..ed2172f --- /dev/null +++ b/content/basic/nginx.md @@ -0,0 +1,213 @@ +--- +title: "Setting Up an NginX Webserver" +date: 2021-07-10 +tags: ["basic"] +--- + +At this point, we should have a domain name and a server and the domain +name should direct to the IP address of the server with DNS records. As +I said in previous articles, the instructions I will give will be for +**Debian**. In this article, other distributions might work a little +differently. + +## Logging in to the server + +We first want to log into our VPS to get a command prompt where we can +set up the web server. I am assuming you are using either MacOS or +GNU/Linux and you know how to open a terminal. On Windows, you can also +use either PuTTY or the Windows Subsystem for Linux. + +Now on Vultr\'s site, you can click on your VPS and you will see that +there is an area that shows you the password for your server at the +bottom here. + +{{< img alt="Find your password" src="/pix/nginx-password.png" link="/pix/nginx-password.png" >}} + +Now pull up a terminal and type: + +```sh +ssh root@{{<hl>}}example.org{{</hl>}} +``` + +This command will attempt to log into your server. It should prompt you +for your password, and you can just copy or type in the password from +Vultr\'s site. + +If you get an error here, you might not have done your [DNS +settings](/basic/dns) right. Double check those. Note you can also replace +the `example.org` with your IP address, but you\'ll want to fix your DNS +settings soon. + +## Installing the Webserver: Nginx + +If the program runs without an error, `ssh` has now logged you into your +server. Let\'s start by running the following commands. + +```sh +apt update +apt upgrade +apt install nginx +``` + +The first command checks for packages that can be updated and the second +command installs any updates. + +The third command installs `nginx` (pronounced Engine-X), which is the +web server we\'ll be using, along with some other programs. + +### Our nginx configuration file + +`nginx` is your webserver. You can make a little website or page, put it +on your VPS and then tell `nginx` where it is and how to host it on the +internet. It\'s simple. Let\'s do it. + +`nginx` configuration files are in `/etc/nginx/`. The two main +subdirectories in there (on Debian and similar OSes) are +`/etc/nginx/sites-available` and `/etc/nginx/sites-enabled`. The names +are descriptive. The idea is that you can make a site configuration file +in `sites-available` and when it\'s all ready, you make a link/shortcut +to it in `sites-enabled` which will activate it. + +First, let\'s create the settings for our website. You can copy and +paste (with required changes) but I will also explain what the lines do. + +Create a file in `/etc/nginx/sites-available` by doing this: + +```sh +nano /etc/nginx/sites-available/{{<hl>}}mywebsite{{</hl>}} +``` + +Note that \"nano\" is a command line text editor. You will now be able +to create and edit this file. By saving, this file will now appear. Note +also I name the file `mywebsite`, but you can name it whatever you\'d +like. + +I\'m going to add the following content to the file. The content **like +this** will be different depending on what you want to call your site. + +```nginx +server { + listen 80 ; + listen [::]:80 ; + server_name {{<hl>}}example.org{{</hl>}} ; + root /var/www/{{<hl>}}mysite{{</hl>}} ; + index index.html index.htm index.nginx-debian.html ; + location / { + try_files $uri $uri/ =404 ; + } +} +``` + +#### Explanation of those settings + +The `listen` lines tell `nginx` to listen for connections on both IPv4 +and IPv6. + +The `server_name` is the website that we are looking for. By putting +`chad.thesiah.xyz` here, that means whenever someone connects to this server +and is looking for that address, they will be directed to the content in +this block. + +`root` specifies the directory we\'re going to put our website files in. +This can theoretically be wherever, but it is conventional to have them +in `/var/www/`. Name the directory in that whatever you want. + +`index` determine what the \"default\" file is; normally when you go to +a website, say `chad.thesiah.xyz`, you are actually going to a file at +`sich/index.html`. That\'s all that is. Note that that this in +concert with the line above mean that `/var/www/sich/index.html`, a +file on our computer that we\'ll create, will be the main page of our +website. + +Lastly, the `location` block is really just telling the server how to +look up files, otherwise throw a 404 error. Location settings are very +powerful, but this is all we need them for now. + +### Create the directory and index for the site + +We\'ll actually start making a \"real\" website later, but let\'s go +ahead and create a little page that will appear when someone looks up +the domain. + +```sh +mkdir /var/www/{{<hl>}}mysite{{</hl>}} +``` + +Now let\'s create an index file inside of that directory, which will +appear when the website is accessed: + +```sh +nano /var/www/{{<hl>}}mysite{{</hl>}}/index.html +``` + +I\'ll add the following basic content, but you can add whatever you +want. This will appear on your website. + +```html +<!DOCTYPE html> +<h1>My website!</h1> +<p>This is my website. Thanks for stopping by!</p> +<p>Now my website is live!</p> +``` + +### Enable the site {#enable} + +Once you save that file, we can enable it making a link to it in the +`sites-enabled` directory: + +```sh +ln -s /etc/nginx/sites-available/{{<hl>}}mywebsite{{</hl>}} /etc/nginx/sites-enabled +``` + +Now we can just `reload` or `restart` to make `nginx` service the new +configuration: + +```sh +systemctl reload nginx +``` + +## The Firewall {#firewall} + +Vultr and some other VPSes automatically install and enable `ufw`, a +firewall program. This will block basically everything by default, so we +have to change that. If you don\'t have `ufw` installed, you can skip +this section. + +We must open up at least ports 80 and 443 as below: + +```sh +ufw allow 80 +ufw allow 443 +``` + +Port 80 is the canonical webserver port, while 443 is the port used for +encrypted connections. We will certainly need that for the next page. + +<aside> + +As you add more services to your website, they might need you to open more ports, but that will be mentioned on individual articles. +(It should be noted that some local services run only for other services on your machine, so you _don't_ need to open ports for every process running locally, _only_ those that directly interact with the internet, although it's common to run those through Nginx for simplicity and security.) + +</aside> + +## Nginx security hint + +By default, Nginx and most other webservers automatically show their +version number on error pages. It\'s a good idea to disable this from +happening because if an exploit comes out for your server software, +someone could exploit it. Open the main Nginx config file +`/etc/nginx/nginx.conf` and find the line `# server_tokens off;`. +Uncomment it, and reload Nginx. + +Remember to [keep your server software up to +date](/../maintenance#update) to get the latest security fixes! + +## We now have a running website! + +At this point you can now type in your website in your browser and this +webpage will appear! + +{{< img alt="The webpage as it appears." src="/pix/nginx-website.png" link="/pix/nginx-website.png" >}} + +Note the \"Not secure\" notification. The next brief step is securing +encrypted connections to your website. diff --git a/content/basic/server.md b/content/basic/server.md new file mode 100644 index 0000000..0b5d320 --- /dev/null +++ b/content/basic/server.md @@ -0,0 +1,97 @@ +--- +title: "Get a Server" +tags: ['basic'] +date: 2021-06-04 +--- +Once you have a [domain name](/basic/domain), you\'ll need a server to +host all your website files on. In general, a server is just a computer +that is constanly broadcasting some services on the internet. + +Servers connected to the internet can be extremely useful with or +without proper websites attached to them. You can be your own website, +email, file-sharing service and much more. + +## Getting a VPS + +A Virtual Personal Server (VPS) is a very cheap and easy way to get a +web server. Without you having to buy expensive equipment. There are a +lot of online businesses that have massive server farms with great +internet connection and big power bills that allow you to rent a VPS in +that farm for pocket change. + +A VPS usually costs \$5 a month. Sometimes slightly more, sometimes +slightly less. That\'s a good price for some internet real-estate, but +in truth, you can host a huge number of websites and services on a +single VPS, so you get a lot more. I might have a dozen websites, an +email server, a chat server and a file-sharing services on one VPS. + +The VPS provider that I\'ll be using for this guide is Vultr, since that +is what I use. Vultr provides a free one-month \$100 credit to anyone +who starts an account through [this referral link of +mine](https://www.vultr.com/?ref=8384069-6G) so you can play around with +their services with impunity. + +## Starting your server in two minutes or less + +[Start an account on Vultr](https://www.vultr.com/?ref=8384069-6G) and +let\'s get started. + +Vultr (and other VPS providers) usually give you a choice in where and +what exactly your VPS is. + +#### Server Location + +In general, it doesn\'t *hugely* matter what physical location you have +your server in. You might theoretically want it close to where you or +your audience might be, but if you host a server in Singapore for an +American audience, they won\'t have to be waiting a perceptibly longer +time to load the site. + +{{< img alt="Pick your servers's location" src="/pix/server-location.png" link="/pix/server-location.png" >}} + +**Some locations might have different abilities and plans than others. +For example, in Vultr, their New York location has optional DDOS +protection and also has some cheaper \$3.50 servers.** + +#### Operating System/Server Type + +{{< img alt="server type" src="/pix/server-type.png" link="/pix/server-type.png" >}} + +I especially recommend **Debian 11** for an operating system for your +server. Debian is the \"classic\" server OS and as such, **I make my +guides on this site for Debian 11**. If you use another OS, just know +that your millage may vary in terms of you might need to change some +instructions here minorly. + +#### Server size + +{{< img alt="server size" src="/pix/server-size.png" link="/pix/server-size.png" >}} + +You finally have a choice in how beefy a server you want. On Vultr, I +recommend getting the cheapest option that is not IPv6 only. + +Web hosting and even moderately complicated sites do not use huge +amounts of RAM or CPU power. If you start doing more intensive stuff +than hosting some webpages and an email server and such, you can always +bump up your plan on Vultr without data loss (it\'s not so easy to bump +down). + +#### Additional features + +{{< img alt="additional features" src="/pix/server-features.png" link="/pix/server-features.png" >}} + +On Vultr, there are some final checkboxes you can select additional +options. **You will want to check *Enable IPv6* and also *Block Storage +Compatible*.** + +We will be setting up IPv6 because it\'s important for future-proofing +your website as more of the web moves to the IPv6 protocol. Block +storage is the ability (if you want) to later rent large storage disks +to connect to your VPS if desired. You just might want that as an +option, so it\'s worth activating now. + +### Done! + +Once you select those settings, your server will automatically be +deployed. Momentarily, you will be able to see your server\'s IP +addresses which will be used for the next brief step: diff --git a/content/bitcoin.md b/content/bitcoin.md new file mode 100644 index 0000000..221ff67 --- /dev/null +++ b/content/bitcoin.md @@ -0,0 +1,105 @@ +--- +title: "Getting a Bitcoin Wallet" +date: 2020-06-28 +icon: "btc.svg" +--- +Let\'s now get a Bitcoin wallet and become able to receive Bitcoin funds +or donations. + +## Wallets + +One of the classical choices for a Bitcoin wallet is Electrum. Go to +[https://electrum.org](https://electrum.org/#home) to download and +install it, or if you are a Linux user, it is probably included in your +distribution\'s package repository. + +### Mobile version? + +Note also that there are mobile/cell phone versions of Electrum for +Android and iOS. I generally advise against using a wallet on a cell +phone for security reasons, but if you would like, you can. + +If you are okay with a mobile wallet, I recommend getting [Cake +Wallet](https://cakewallet.com/), which can use Electrum-style Bitcoin +wallets, but also Monero and Litecoin. + +## Generating a Wallet + +Once you open Electrum (or Cake Wallet), you can choose to create a new +wallet. Name it whatever you want and choose the \"Standard Wallet\" +option. + +I will also note that if you are paranoid, it is perfectly possible to +generate a wallet without connection to the internet. + +### Your Seed is your money. + +Now choose the \"Create a new seed\" option when creating the wallet. +That will randomly produce a \"seed\" of 12 words. + +{{< img alt="bitcoin seed" src="/pix/bitcoin-01.png" link="/pix/bitcoin-01.png" >}} + +**These words are your money.** Once you are shown them, **immediately** +write them down on physical paper, and you will be storing this +somewhere it will not be lost or found. You can memorize these twelve +words if you trust your memory. + +These twelve words unlock all of the funds/addresses you will have on +this wallet. Whoever has your seed has the ability to spend your money. + +Note obviously that I have included a picture of a seed phrase above in +this tutorial. I or anyone else would be stupid to ever send Bitcoin to +the following addresses since the seed phrases are now public. + +Once you have written down your seed, click \"Next\" and Electrum will +have you input that seed again to ensure you\'ve written it down. + +You will also be asked to supply a password. This password merely +encrypts your wallet file on this computer so you don\'t have to retype +your seed phrase each time you open Electrum. Note that anyone with your +seed phrase can still obtain your funds. This password is only +protection on your computer here. + +## Managing your Wallet + +Once your wallet is generated and opened you will be at the wallet page. +First, I recommend opening the \"View\" menu and unhiding all the +different tabs. + +{{< img alt="electrum options" src="/pix/bitcoin-02.png" link="/pix/bitcoin-02.png" >}} + +### Addresses + +The address tab contains all the many Bitcoin addresses generated by +your seed phrase. In fact, as you use these up, the wallet will +automatically add more. + +These addresses (which will all be generated with `bc1` at the +beginning) can be used by others to send you Bitcoins. Someone can just +copy-and-paste the address into their wallet to send you funds. + +{{< img alt="bitcoin addresses" src="/pix/bitcoin-03.png" link="/pix/bitcoin-03.png" >}} + +### Receive + +Click on the \"Receive\" tab and then click \"New Address.\" That will +pick your first unused address which will appear on the right side. You +could copy this from the \"Addresses\" tab, but this tab also generates +a QR code which will appear to the right as well if you click on the +\"QR Code\" subtab. + +{{< img alt="receive qr code" src="/pix/bitcoin-04.png" link="/pix/bitcoin-04.png" >}} + +#### What is the QR code for? + +In case you don\'t know, a QR code is a way of storing text information +in a format that can be scanned by a phone. If someone has a wallet +program on a phone, they can easily scan the QR code on another screen +to avoid having to copy your address over or even worse, write it +manually. + +### Let\'s receive donations on our website. + +Save the QR code and the wallet address it corresponds to (starting in +`bc1`). Now simply put these on your website and anyone can send Bitcoin +to them. Bitcoin users will know how to scan and use them. diff --git a/content/btcpay.md b/content/btcpay.md new file mode 100644 index 0000000..11ed7ed --- /dev/null +++ b/content/btcpay.md @@ -0,0 +1,57 @@ +--- +title: "BTCPay" +icon: 'btcpay.svg' +tags: ['service'] +short_desc: "Host your own payment processor, powered by Bitcoin." +draft: true +--- + +```sh +apt install nginx python3-certbot-nginx tor postgresql postgresql-contrib iptables iptables-persistent +``` + + *filter + :INPUT ACCEPT [0:0] + :FORWARD ACCEPT [0:0] + :OUTPUT ACCEPT [0:0] + -A INPUT -i lo -j ACCEPT + -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # SSH + -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT # BTCPay HTTP + -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT # BTCPay HTTPS + -A INPUT -p tcp -m tcp --dport 8333 -j ACCEPT # Bitcoind P2P + -A INPUT -p tcp -m tcp --dport 9735 -j ACCEPT # Lightning P2P + -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + COMMIT + +`iptables-restore > iptables.txt` netfilter-persistent save + + echo "ControlPort 9051 + CookieAuthentication 1" >> /etc/tor/torrc + +certbot \--nginx -d pay.cedars.xyz \--agree-tos +\--register-unsafely-without-email vim /etc/nginx/sites-available/btcpay + +## Building Bitcoin + +Now we can install the Bitcoin node and daemon software. For safety\'s +sake, we will install it from source. + +First, we install the build dependencies: + + apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils python3 libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev git + +Now we can download the Bitcoin source code from the official +repository: + + git clone https://github.com/bitcoin/bitcoin + cd bitcoin + +Now, we compile, then install it. Compiling the software will take some +time. + + ./autogen.sh + ./configure + make + make install + +[[Next:\<++\>](%3C++%3E)]{.next} diff --git a/content/calibre.md b/content/calibre.md new file mode 100644 index 0000000..e1e9faa --- /dev/null +++ b/content/calibre.md @@ -0,0 +1,116 @@ +--- +title: "Calibre" +date: 2021-08-03 +icon: "calibre.png" +short_desc: 'A public or private digital library.' +tags: ['service'] +--- + +The Calibre library server is a great way to store your eBooks. It +allows you to: + +- Share your books with others. +- Easily transfer your books between devices and access them from + anywhere. + +## Installation + +Install the Calibre package. You might also want rsync to upload books. + +```sh +apt install -y calibre rsync +mkdir /opt/calibre +``` + +Either upload your existing library using `rsync`. For example to +`/opt/calibre/`. + +```sh +cd ~/Documents +rsync -avuP your-library-dir root@{{<hl>}}example.org{{</hl>}}:/opt/calibre/ +``` + +Or create a library and add a book to it: + +```sh +cd /opt/calibre +calibredb add book.epub --with-library your-library +``` + +For more information about the `calibredb` command see `man calibredb`. + +Add a new user to protect your server: + +```sh +calibre-server --manage-users +``` + +## Creating a service + +Create a new file `/etc/systemd/system/calibre-server.service` and add +the following: + +```systemd +[Unit] +Description=Calibre library server +After=network.target + +[Service] +Type=simple +User=root +Group=root +ExecStart=/usr/bin/calibre-server --enable-auth --enable-local-write /opt/calibre/your_library --listen-on 127.0.0.1 + +[Install] +WantedBy=multi-user.target +``` + +You can change the port with the `--port` prefix. Additional information +`man calibre-server`. + +Issue `systemctl daemon-reload` to apply the changes. + +Enable and start the service. + +```sh +systemctl enable calibre-server +systemctl start calibre-server +``` + +## A reverse proxy with Nginx + +Create a new file `/etc/nginx/sites-available/calibre` and enter the +following: + +```nginx +server { + listen 80; + client_max_body_size 64M; # to upload large books + server_name {{<hl>}}calibre.example.org{{</hl>}} ; + + location / { + proxy_pass http://127.0.0.1:8080; + } +} +``` + +Issue a Let\'s Encrypt certificate. [Detailed instructions and additional information](/basic/certbot). + +```sh +certbot --nginx +``` + +Now just go to **calibre.example.org**. The server will request an +username and a password. + +{{< img src="/pix/calibre/calibre-1.png" alt="calibre" >}} + + +After login you will see something like this. + +{{< img src="/pix/calibre/calibre-2.png" alt="calibre" >}} + +## Contribution + +Author: rflx -- [website](https://rflx.xyz) \-- XMR: +`48T5XpHTXAZ5Nn8YCypA4aWn1ffQLHJkFGDArXQB6cmrP6cqLY72cu7CR2iq2MmL5Ndu3d47e5MKjGpL4prYgdrTCFAHD9c` diff --git a/content/cgi.md b/content/cgi.md new file mode 100644 index 0000000..5f293e9 --- /dev/null +++ b/content/cgi.md @@ -0,0 +1,210 @@ +--- +title: "Server-Side Scripting with CGI" +date: 2021-07-25 +tags: ['server'] +--- +The basic website tutorial here describes how to set up a static website +--- one that just serves HTML files saved on your server, and until you +change something manually, the same content will be served each time a +given page is requested. This is perfectly enough for most personal +website needs. This is how blogs should be implemented, instead of +relying on bloatware like WordPress! + +But sometimes you genuinely *do* need something more. You need your +website to serve different contents depending on the time, on who the +requester is, on the contents of a database, or maybe process user input +from a form. + +## CGI + +CGI, or the Common Gateway Interface, is a specification to allow you, +the server owner, to program your web server using pretty much any +programming language you might know. The specification is almost as old +as the Internet itself and for a long time CGI scripting was the primary +method of creating dynamic websites. + +CGI is a very simple specification indeed. You write a script in your +favorite language, the script receives input about the request in +environment variables, and whatever you print to the standard output +will be the response. Most likely, though, you will want to use a +library for your language of choice that makes a lot of this +request/response handling simpler (e.g. parsing query parameters for +you, setting appropriate headers, etc.). + +### Limitations of CGI + +While in theory you could implement any sort of functionality with CGI +scripts, it\'s going to get difficult managing a lot of separate scripts +if they\'re supposed to be working in tandem to implement a dynamic +website. If you want to build a full out web application, you\'d +probably be better off learning a web framework than gluing together +Perl scripts. + +That said, just as most of the web could be replaced with static +websites, much of the remaining non-static web could be replaced with a +few simple scripts, rather than bloated Ruby on Rails or Django +applications. + +## Let\'s write a CGI script! + +We\'ll implement a simple example CGI script. I\'ll use Ruby for this +tutorial, but you\'ll be able to follow along even if you don\'t know +Ruby, just treat it as pseudocode then find a CGI library for your +language. + +### The working example + +Our working example will be the Lazy Calculator. Yeah, you\'re probably +tired of seeing calculator examples in every programming tutorial, but +have you ever implemented one that takes the weekends off? + +Here\'s how it will work. When in a browser you submit a request to your +website like + +```txt +example.com/calculator.html?a=10&b=32 +``` + +you will receive a page with the result of the addition of 10 and 32: +42. + +*Unless* you send your request on a weekend. Then the website will +respond with + +```txt +I don't get paid to work on weekends! Come back Monday. +``` + +This example will show a few things that CGI scripts can do that you +wouldn\'t have been able to get using just file hosting in your web +server: + +- getting inputs from the user; +- getting external information (here just the system time, but you + could imagine instead connecting to a database); +- using the above to create dynamic output. + +### The code + +Here\'s an implementation of the lazy calculator as a Ruby CGI script: + +```ruby +#!/bin/env ruby + +require 'cgi' +require 'date' + +cgi = CGI.new +today = Date::today + +a = cgi["a"].to_i +b = cgi["b"].to_i + +if today.saturday? || today.sunday? + cgi.out do + "I don't get paid to work on weekends! Come back Monday." + end +else + cgi.out do + (a + b).to_s + end +end +``` + +Let\'s go through what\'s happening here. + +### The shebang line + +CGI works by pointing your web server to an executable program. A Ruby +or Python script by itself is not immediately executable by a computer. +But on Unix-like systems you can specify the program that will be able +to execute your file in its first line if it starts with `#!` (known as +the shebang; read more about it on +[Wikipedia](https://en.wikipedia.org/wiki/Shebang_(Unix))). + +So if you\'re going to be using a scripting language, you\'ll probably +need the appropriate shebang line at the top of your script. If you use +a compiled language, you\'ll just point your web server to the compiled +executable binary. + +### Query parameters + +The next interesting lines of code are where we set the variables `a` +and `b`. Here we are getting user inputs from the request. + +In the example request we mentioned above +(`example.com/calculator.html?a=10&b=32`), the part starting from the +question mark, `?a=10&b=32`, is the *query string*. This is how users +can submit parameters with their web requests. Usually these parameters +are set by e.g. a form on your website, but in our simple example we\'ll +be just manually manipulating the URL. + +The query string contains key-value pairs. The Ruby CGI library makes +them available in the `CGI` object it provides. We just need to index it +with the desired key, and we\'ll get the corresponding value. + +### Wrapping it up + +The remaining parts of the code should be pretty self-explanatory. We +get today\'s date, check if it\'s a Saturday or a Sunday, and depending +on that, we instruct the CGI library to output either the answer, or a +\"come back later\" message. + +The Ruby library by default returns an HTML response, so we really +should have wrapped our outputs in some `html`, `body`, etc. tags. +Alternatively, we could have specified that the response is just plain +text with + +```txt +cgi.out 'text/plain' do +``` + +In general, your CGI library will probably have ways of specifying all +sorts of HTTP response headers, like status code, content type, etc. + +## Making it work + +We have a CGI script, now let\'s point our web server to it. + +### Installing FastCGI + +If you\'re using Nginx, install `fcgiwrap`: + +```sh +apt install fcgiwrap +``` + +This installs the necessary packages for Nginx to use FastCGI --- a +layer between your web server and CGI script that allows for faster +handling of scripts than if the web server had to handle it all by +itself. + +Other web servers will probably have a similarly simple way of enabling +FastCGI, or you can look into other methods for launching CGI scripts. + +### Nginx configuration + +In the configuration file for your website, add something like the +following: + +```nginx +location /calculator.html { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/local/bin/lazy-calculator.rb; + fastcgi_param QUERY_STRING $query_string; + fastcgi_pass unix:/run/fcgiwrap.socket; +} +``` + +`fastcgi_param` directives specify various parameters for FastCGI. +`SCRIPT_FILENAME` should point to your executable. For `QUERY_STRING`, +we just copy Nginx\'s `$query_string` variable. You might want to pass +other information to your CGI script as well, see for example [the +Debian wiki](https://wiki.debian.org/nginx/FastCGI) for a more detailed +example, including pointing to an entire directory of CGI scripts, +rather than adding each one by hand to your web server config. + +## Contribution + +- Martin Chrzanowski \-- [website](https://m-chrzan.xyz), + [donate](https://m-chrzan.xyz/donate.html) diff --git a/content/cgit.md b/content/cgit.md new file mode 100644 index 0000000..a2da04c --- /dev/null +++ b/content/cgit.md @@ -0,0 +1,149 @@ +--- +title: "Cgit" +date: 2021-09-14 +short_desc: "A hyperfast web frontend for git repositories." +icon: "cgit.svg" +tags: ["service"] +--- + +Once you have your server hosting your git repositories, you might want +to allow others to browse your repositories on the web. Cgit is a Free +Software that allows browsing git repositories through the web. + +Note that Cgit is a read-only frontend for Git repositories and doesn\'t +have issues, pull requests or user management. If that\'s what you want, +consider installing [Gitea](/gitea) instead. + +## Installing cgit and fcgiwrap + +### Install fcgiwrap + +NGINX doesn\'t have the capability to run CGI scripts by itself, it +depends on an intermediate layer like fcgiwrap to run CGI scripts like +cgit: + +```sh +apt install fcgiwrap +``` + +And now we can install cgit itself with: + +```sh +apt install cgit +``` + +## Setting up NGINX + +You should have an NGINX server running with a TLS certificate by now. +Add the following configuration to your server to pass the requests to +Cgit, while serving static files directly: + +```nginx +server { + listen 443 ssl; + listen [::]:443 ssl; + ssl_certificate /etc/ssl/nginx/{{<hl>}}git.example.org{{</hl>}}.crt; + ssl_certificate_key /etc/ssl/nginx/{{<hl>}}git.example.org{{</hl>}}.key; + server_name {{<hl>}}git.example.org{{</hl>}}; + + root /usr/share/cgit ; + try_files $uri @cgit ; + + location ~ /.+/(info/refs|git-upload-pack) { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + fastcgi_param PATH_INFO $uri; + fastcgi_param GIT_HTTP_EXPORT_ALL 1; + fastcgi_param GIT_PROJECT_ROOT /var/git; + fastcgi_param HOME /var/git; + fastcgi_pass unix:/run/fcgiwrap.socket; + } + + location @cgit { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi; + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_pass unix:/run/fcgiwrap.socket; + } +} +``` + +Then get NGINX to reload your configuration. This configuration also enables +cloning via HTTPS, so make sure to point the `fastcgi_param GIT_PROJECT_ROOT` +to the directory where you store your repositories. + +## Configuring cgit + +You\'ve got cgit up and running now, but you\'ll probably see it without +any style and without any repository. To change this, we need to +configure Cgit to our liking, by editing `/etc/cgitrc`. + +```txt +css=/cgit.css +logo=/cgit.svg +virtual-root=/ +clone-prefix=https://{{<hl>}}git.example.org{{</hl>}} + +# Title and description shown on top of each page +root-title={{<hl>}}Chad's git server{{</hl>}} +root-desc={{<hl>}}A web interface to SiCh's git repositories, powered by Cgit{{</hl>}} + +# The location where git repos are stored on the server +scan-path=/var/git/ +``` + +This configuration assumes you followed the [git hosting guide](/git) +and store your repositories on the `/var/git/` directory. + +Cgit\'s configuration allows changing many settings, as documented on +the cgitrc(5) manpage installed with Cgit. + +### Changing the displayed repository owner + +Cgit\'s main page shows each repo\'s owner, which is \"git\" in case you +followed the git hosting guide, but you might want to change the name to +yours. Cgit shows the owner\'s system name, so you need to modify the +git user to give it your name: + +```sh +usermod -c "{{<hl>}}Your Name{{</hl>}}" git +``` + +### Changing the repository description + +Navigate to your bare repository on the server and edit the +`description` file inside it + +### Displaying the repository idle time + +To do this, we need to create a post-receive hook for each repository +that updates the file cgit uses to determine the idle time. Inside your +repository, create a file `hooks/post-receive` and add the following +contents: + +```sh +#!/bin/sh + +agefile="$(git rev-parse --git-dir)"/info/web/last-modified + +mkdir -p "$(dirname "$agefile")" && +git for-each-ref \ + --sort=-authordate --count=1 \ + --format='%(authordate:iso8601)' \ + >"$agefile" +``` + +And give it execution permissions with: + +```sh +chmod +x hooks/post-receive +``` + +Next time you push to that repository, the idle time should reset and +show the correct value. + +## Contribution + +- Ariel Costas -- [website](https://costas.dev) diff --git a/content/coturn.md b/content/coturn.md new file mode 100644 index 0000000..b49c47c --- /dev/null +++ b/content/coturn.md @@ -0,0 +1,115 @@ +--- +title: "Coturn" +date: 2022-03-29 +short_desc: 'A STUN and TURN server that allows users to perform WebRTC calls while being behind NATs.' +icon: "webrtc.svg" +img: "webrtc.svg" +tags: ['service'] +--- + +[Coturn](https://github.com/coturn/coturn) is a libre **STUN** and **TURN** server software that allows users of internet applications or protocols (Such as [XMPP](/prosody) and [Matrix](/matrix)) to perform WebRTC **voice and video calls** despite them being behind NATs. + +If you want to add video and voice calling natively to your XMPP or Matrix server (or a myriad of various other applications), you'll need to install Coturn and configure it appropriately. + +### Note on ejabberd +If you're installing [ejabberd,](/ejabberd) then *you don't need Coturn.* Ejabberd comes with a TURN server built-in, and you should only setup ejabberd to connect to Coturn if you intend on running **multiple chat services** like Matrix and XMPP. + +## Installation + +Coturn is available in the Debian repositories: + +```sh +apt install coturn +``` + +## Configuration + +### Base configuration + +Coturn\'s configuration file is `/etc/turnserver.conf`. There are a few +aspects that need to be changed in order to get a fully-functioning +turnserver. + +Here is an example of some sane defaults: + +```txt +server-name={{<hl>}}turn.example.org{{</hl>}} +realm={{<hl>}}turn.example.org{{</hl>}} +listening-ip=your_public_ip + +listening-port=3478 +min-port=10000 +max-port=20000 + +## The "verbose" option is useful for debugging issues +verbose +``` + +### Authentication + +There are two options for authentication on a turnserver: + +1. **Usernames** and **passwords** +2. **Authentication secrets** + +Depending on what self-hosted service is being used in conjunction with Coturn, you may need one or the other of these two options. + +#### Usernames and Passwords + +To utilize username and password authentication with Coturn, add the following configuration in `turnserver.conf`: + +```txt +lt-cred-mech +user=username:password +``` + +#### Authentication Secrets + +To utilize authentication secrets with Coturn, add the following +configuration in `turnserver.conf`: + +```txt +use-auth-secret +static-auth-secret={{<hl>}}your_auth_secret{{</hl>}} +``` + +### TURNS (TLS Encryption) + +Some self-hosted services may support the use of **TURNS:** An encrypted version of TURN, which allows for WebRTC connections to be established with the use of an encrypted TLS tunnel, just like HTTPS allows for encrypted viewing of websites. + +*Note: This does **not** affect the encryption of the audio or video feeds. This only makes the requests to the TURN servers encrypted, which is still desireable for security. Any encryption of the call contents will be handled by the client and server of the application you are using.* + +To utilize TURNS, certificates need to be declared for **turn.example.org** in `turnserver.conf`: + +```txt +cert=/etc/letsencrypt/live/{{<hl>}}turn.example.org{{</hl>}}/fullchain.pem +pkey=/etc/letsencrypt/live/{{<hl>}}turn.example.org{{</hl>}}/privkey.pem +``` + +In this example, Letsencrypt certificates generated with `certbot` are used. + + + +## Starting Coturn + +After all configuration changes are complete, Coturn can be started with its systemd daemon: + +```sh +systemctl restart coturn +``` + +## Configuring your application + +At this stage, you should look in your application's own guide on how to set the TURN and STUN server settings. Configure it to point at **turn.example.org** and use either your **username and password pair** or your super-secure **authentication secret.** + +- [How to configure TURN on ejabberd](/ejabberd#voice-and-video-calls) +- [How to configure TURN on Prosody](/prosody#voice-and-video-calls) +- [How to configure TURN on Matrix Synapse](/matrix#voice-and-video-calls) +- [How to configure TURN on Matrix Dendrite](/dendrite#voice-and-video-calls) + +Congratulations! You've successfully setup a Coturn server! + +--- + +Written by [Denshi.](https://denshi.org) +Donate Monero at: `48dnPpGgo8WernVJp5VhvhaX3u9e46NujdYA44u8zuMdETNC5jXiA9S7JoYMM6qRt1ZcKpt1J3RZ3JPuMyXetmbHH7Mnc9C` diff --git a/content/cron.md b/content/cron.md new file mode 100644 index 0000000..f06a2a4 --- /dev/null +++ b/content/cron.md @@ -0,0 +1,173 @@ +--- +title: "Cronjobs" +date: 2020-07-01 +tags: ["server"] +--- + +Cron is a service that lets you run scheduled tasks on a computer. These tasks +are called **cronjobs.** If you have already followed the initial course you +will have already used cron when you set up Certbot, but we'll explain how they work generally here. + +## What tasks would I want to schedule? + +You can schedule anything! Some examples of what you might have done +already include: + +- `updatedb` to update your `locate` database to let you quickly search for files +- `certbot` to update renewing of your https certs + +Some tasks that you might _want_ to schedule may include: + +- Package updates - if you really just want to leave your server alone + you can automate updating packages on your server +- Backups - you may want to backup certain files every day and some + every week, this is possible with cron + +And many more, anything you can do can be turned into a cronjob. + +## Basic Cronjobs + +This the preferred method for personal tasks and scripts; it\'s also the +easiest to get started with. Run the command `crontab -e` to access your +user\'s crontab + +Once you have figured out the command you want to run you need to figure +out how often you want to run it and when. I am going to schedule my +system updates once a week at 3:30 AM on Mondays. + +We now have to convert this time (Every Monday at 3:30 AM) into a cron +time. Cron uses a simple but effective way of scheduling when to run +things. + +Crontab expressions look like this `* * * * * command-to-run` The five +elements before the command tell when the command is supposed to be run +automatically. + +So for our Monday at 3:30 AM job we would do the following: + +```txt + .---------------- minute (0 - 59) + | .------------- hour (0 - 23) + | | .---------- day of month (1 - 31) + | | | .------- month (1 - 12) + | | | | .---- day of week (0 - 6) + | | | | | + * * * * * +30 3 * * 1 apt -y update && apt -y upgrade +``` + +### Some notes + +- On the day of the week option, Sunday is 0 and counting up from + there, Saturday will be 6. +- `*` designates \"everything\". Our command above has a `*` in the + day of month and month columns. This means it will run regardless of + the day of the month or month. +- The hour option uses 24 hour time. 3 = 3AM, while we'd use 15 for 3PM. + +### More examples + +Let\'s add another job, our backup job (for the purpose of this our +backup command is just called `backup`). We want to run `backup` every +evening at 11PM. Once we work out the timings for this we can add this new job +to the same file as the above by running `crontab -e` This would mean our +full crontab would look like this: + +```txt +0 23 * * * backup +``` + +### Consecutive times + +Suppose we want a command to run every weekday. We know we can put `1` +(Monday), but we can also use `1-5` to signify from day 1 (Monday) to +day 5 (Friday). + +```txt +0 6 * * 1-5 echo "Wakey, wakey, wagie!" >> /home/wagie/alarm +``` + +The above `echo` command runs every Monday through Friday at 6:00AM. + +### Non-consecutive times + +We can also randomly specify non-consecutive arguments with a comma. +Suppose you have a script you want to run at the midday of the 1st, +15th, and 20th day of every month. You can specify that by putting +`1,15,20` for the day of the month argument: + +```txt +0 12 1,15,20 * * /usr/bin/pay_bills_script +``` + +### \"Every X minutes/days/months\" + +We can also easily run a command every several minutes or months, +without specifying the specific times: + +```txt +*/15 * * * * updatedb +``` + +This cronjob will run the `updatedb` command every 15 minutes. + +### Beware of this Rookie Mistake Though\... + +Suppose you want to run a script once every other month. You might be +_tempted_ write this: + +```txt +* * * */2 * +``` + +That might _feel right_, but this script _will be running once every +minute during that every other month_. You should specify the first two +arguments, because with `*` it will be running every minute and hour! + +```txt +0 0 1 */2 * +``` + +This makes the command run _only_ at 0:00 (12:00AM) on the first day of +every two months, which is what we really want. + +Consult the website [crontab.guru](https://crontab.guru) for an +intuitive and interactive tester of cronjobs. + +## User vs. Root Cronjobs + +It is important to note that user accounts all have different cronjobs. +If you have a user account `chad` and edit his crontab with +`crontab -e`, the commands you add will be run as the `chad` user, not +`root` or anyone else. + +Bear in mind that if you need root access to run a particular command, +you will usually want to add it as root. + +## System-wide cron directories + +`crontab -e` is the typical interface for adding cronjobs, but it\'s +important to at least know that system-wide jobs are often stored in the +file directory. Some programs which need cronjobs will automatically +install them in the following way. + +Run the command `ls /etc/cron*` and you should see a list of directories and +their contents. The list of directories should look something like the below: + +- /etc/cron.d _This is a crontab like the ones that you create with_ + `crontab -e` +- /etc/cron.hourly +- /etc/cron.daily +- /etc/cron.weekly +- /etc/cron.monthly + +The directories cron.{hourly,daily,weekly,monthly} are where you can put +**scripts** to run at those times. You don\'t put normal cron entries +here. I prefer to use these directories for system wide jobs that don\'t +relate to an individual user. + +## Contribution + +- Mark McNally \-- [website](https://mark.mcnally.je), + [Youtube](https://www.youtube.com/channel/UCMiInY8BhSUtCarO6uu6i_g) +- Edits and examples by Luke diff --git a/content/dendrite.md b/content/dendrite.md new file mode 100644 index 0000000..c949a9d --- /dev/null +++ b/content/dendrite.md @@ -0,0 +1,292 @@ +--- +title: "Matrix Dendrite" +date: 2023-03-21 +icon: 'element.svg' +tags: ['service'] +short_desc: "A faster server implementation of Matrix." +--- + +The Matrix protocol's default implementation, [Synapse,](/matrix) is very memory and processor hungry, mostly due to it being written in the *interpreted Python programming language.* This means that running Synapse on less powerful servers may **take a lot of resources away** from other services. If you need a more efficient and less memory-intensive but still fully functional Matrix server, then [Dendrite](https://github.com/matrix-org/dendrite) is for you. + +## Prerequisities + +### DNS Records and Delegation + +You are **not required** to run a Matrix server under a subdomain (like **matrix.example.org**), regardless of server software. You can run your server under **example.org** to ensure usernames and rooms look like `@user:example.org` and `#room:example.org` respectively. + +Because Matrix uses **HTTP** for transport over the SSL ports (443 and 8448), you'll have to configure NGINX for it to work. This can cause confusion, especially if you're running both a [static website](/basic/nginx/) and Matrix server under the same domain (like **example.org**). + +Depending on your setup, there are 2 different configurations to achieve this: + +1. Your *desired* domain (**example.org**) has an [A DNS record](/basic/dns/) that already poinst to your desired Matrix server, so you can configure this or add to your existing NGINX static site configuration to setup Matrix. + +2. You wish to use Matrix with your *desired* domain (**example.org**) but this domain's A record points to a different server, accessible through another domain (like **matrix.example.org**). In this case, look into [delegation.](https://matrix-org.github.io/synapse/latest/delegate.html) + + +### NGINX Configuration + +Here's an example configuration for a Matrix server running under **example.org:** + +```nginx +server { + server_name {{<hl>}}example.org{{</hl>}}; + + listen 80; + listen [::]:80; + + listen 443 ssl http2 default_server; + listen [::]:443 ssl http2 default_server; + + listen 8448 ssl http2 default_server; + listen [::]:8448 ssl http2 default_server; + + location ~* ^(\/_matrix|\/_synapse|\/_client) { + proxy_pass http://localhost:8008; + proxy_set_header X-Forwarded-For $remote_addr; + client_max_body_size {{<hl>}}50M{{</hl>}}; + } + + # These sections are required for client and federation discovery + # (AKA: Client Well-Known URI) + location /.well-known/matrix/client { + return 200 '{"m.homeserver": {"base_url": "https://{{<hl>}}example.org{{</hl>}}"}}'; + default_type application/json; + add_header Access-Control-Allow-Origin *; + } + + location /.well-known/matrix/server { + return 200 '{"m.server": "{{<hl>}}example.org{{</hl>}}:443"}'; + default_type application/json; + add_header Access-Control-Allow-Origin *; + } +} +``` + +Let's say you also want to run a **static website** under **example.org.** This can be achieved by adding these usual lines under the `server` section: + +```nginx + # Basic static site configuration, like any other site + root /var/www/{{<hl>}}example.org{{</hl>}}; + index index.html; + + location / { + try_files $uri $uri/ =404; + } +``` + +#### Certbot Certificates + +Finally, make sure to download and enable TLS certificates for this setup by using the `certbot` command: + +```sh +certbot --nginx -d {{<hl>}}example.org{{</hl>}} +``` + +## Installation + +Dendrite has no official distribution packages at the time of writing. To install and run it, you must first install *the Go programming language* and then compile the Dendrite software from source. + +### Installing Go + +First, download the latest Go tarball: +```sh +curl -fLO "https://dl.google.com/go/$(curl https://go.dev/VERSION?m=text).linux-amd64.tar.gz" +``` + +Then, extract the contents to `/usr/local`, which will create the directory `/usr/local/go`: +```sh +tar -C /usr/local -xzfv go*.tar.gz +``` + +Then finally, make sure the `/usr/local/go/bin/` path is accessible in the `$PATH` variable for every user by editing `/etc/profile` and adding the following line: + +```sh +export PATH=$PATH:/usr/local/go/bin +``` + +### Compiling and Installing Dendrite + +Besides Go, we also need the `build-essential` package to compile software: + +```sh +apt install build-essential +``` + +Now download the Dendrite repository using `git` and change directory to it: + +```sh +git clone https://github.com/matrix-org/dendrite +cd dendrite +``` +Finally, compile Dendrite using `go build`: + +```sh +go build -o bin/ ./cmd/... +``` + +*This might take a few minutes,* but once the process is finished you should find the final Dendrite programs populating the `bin/` directory. + +## Configuration + +To configure Dendrite, begin by coping the `dendrite-sample.yaml` configuration file to `dendrite.yaml`: + +```sh +cp dendrite-sample.yaml dendrite.yaml +``` + +To configure your domain, edit the following under the `global:` section: + +```yaml +server_name: {{<hl>}}example.org{{</hl>}} +``` + +### Server Signing Keys + +Generate the signing keys used by your homeserver with the following command, ran from the Dendrite repository: + +```sh +./bin/generate-keys --private-key matrix_key.pem +``` + +You can also import old keys from Synapse, by specifying their file path in the `old_private_keys:` variable in `dendrite.yaml`. + +### Database Configuration + +By default, Dendrite will create SQLite databases for all its various components. On most server deployments however, it is beneficial to run Dendrite with a more efficient database backend, like PostgreSQL. + +Begin by installing PostgreSQL: + +```sh +apt install postgresql +``` + +Then start the daemon: + +```sh +systemctl restart postgresql +``` + +Now create a user named `dendrite` to manage your database: + +```sh +su -c "createuser --pwprompt dendrite" postgres +``` + +And finally, create the actual database: + +```sh +su -c "psql -c 'CREATE DATABASE dendrite ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER dendrite;'" postgres +``` + +Now we can configure this in `dendrite.yaml` using the `connection_string:` option under the `database:` section: + +```yaml + database: + connection_string: postgres://dendrite:{{<hl>}}password{{</hl>}}@localhost/dendrite?sslmode=disable + max_open_conns: 90 + max_idle_conns: 5 + conn_max_lifetime: -1 +``` + +**Important:** If you find `database:` sub-sections under the individual Dendrite modules in `dendrite.yaml` (`app_service_api`, `federation_api`, `key_server`, `media_api`, `mscs`, `room_server`, `sync_api` and `user_api`), make sure to **comment these out** as these would override the global `database` configuration. + +### Voice and Video Calls + +Dendrite supports native voice and video calling by connecting to a compatible TURN and STUN server. + +Begin by setting up the [coturn](/coturn) TURN server using the guide provided, setting either a shared secret or a username-password pair for authentication. + +Then edit the `turn:` section in `dendrite.yaml`: + +```yaml + turn: + turn_user_lifetime: "5m" + turn_uris: + - turn:{{<hl>}}turn.example.org{{</hl>}}?transport=udp + - turn:{{<hl>}}turn.example.org{{</hl>}}?transport=tcp + + turn_shared_secret: "{{<hl>}}your_shared_secret{{</hl>}}" + + # If your TURN server requires static credentials, then you will need to enter + # them here instead of supplying a shared secret. Note that these credentials + # will be visible to clients! + # turn_username: "" + # turn_password: "" +``` + +### File Directory and Ownership + +Like [Synapse,](/matrix) it's recommended you place the Dendrite program files in `/opt` to keep your server organized: + +```sh +mv dendrite/ /opt/ +``` + +It's also recommended you create a `dendrite` user, who will own the `/opt/dendrite` directory, so it can be used to run Dendrite as a service: + +```sh +useradd dendrite -d /opt/dendrite +chown -R dendrite:dendrite /opt/dendrite +``` + +### Setting up a systemd Service + +Now setup a **systemd service** in `/etc/systemd/system/dendrite.service` to run Dendrite automatically for you. Make sure to set the `WorkingDirectory` to the directory where your Dendrite repository is located! + +```systemd +[Unit] +Description=Dendrite (Matrix Homeserver) +After=syslog.target +After=network.target +After=postgresql.service ## Remove this if you're not using PostgreSQL + +[Service] +Environment=GODEBUG=madvdontneed=1 +RestartSec=2s +Type=simple +User={{<hl>}}dendrite{{</hl>}} +Group={{<hl>}}dendrite{{</hl>}} +WorkingDirectory={{<hl>}}/opt/dendrite/{{</hl>}} +ExecStart={{<hl>}}/opt/dendrite/bin/dendrite{{</hl>}} +Restart=always +LimitNOFILE=65535 + +[Install] +WantedBy=multi-user.target +``` + +Refresh the systemd daemon configuration by running: + +```sh +systemctl daemon-reload +``` + +And finally, **run Dendrite** by running: + +```sh +systemctl restart dendrite +``` + +## Using Dendrite + +### Creating Users + +To create users on the Dendrite server, first ensure it is running. Then, enter a secret value into the `registration_shared_secret:` field under the `client_api` section: + +```yaml +registration_shared_secret: "your_secret_string" +``` + + Then, use the `./bin/create-account` tool located in its repository: + +```sh +./bin/create-account -config dendrite.yaml -username {{<hl>}}user{{</hl>}} -admin +``` +This will automatically prompt you for a password. + +Congratulations! You've installed the Matrix Dendrite homeserver. Now you can login with any [Matrix client](https://matrix.org/clients/) you wish, and chat securely. + +--- +Written by [Denshi.](https://denshi.org) +Donate Monero at: +`48dnPpGgo8WernVJp5VhvhaX3u9e46NujdYA44u8zuMdETNC5jXiA9S7JoYMM6qRt1ZcKpt1J3RZ3JPuMyXetmbHH7Mnc9C` diff --git a/content/dns-over-http.md b/content/dns-over-http.md new file mode 100644 index 0000000..176ec33 --- /dev/null +++ b/content/dns-over-http.md @@ -0,0 +1,148 @@ +--- +title: "Run your own DNS over HTTPS server." +tags: ["service"] +draft: true +--- + +Encrypted DNS can be a great tool for your online privacy if it\'s +hosted by a trustworthy entity, and who can you trust more with your +data than yourself? + +## Installing Unbound. + +First of all, we need to install our DNS server, Unbound. Unbound is a +validating, recursive and caching DNS server. + +```sh +apt install -y unbound +``` + +### Now that Unbound is installed, we will configure it a bit. + +Using your favorite editor, edit the file `/etc/unbound/unbound.conf` +and add the following values, if they don\'t exist already: + +```` +include-toplevel: "/etc/unbound/unbound.conf.d/*.conf" +server: + log-queries: no + log-replies: no + aggressive-nsec: yes + ratelimit: 150 + verbosity: 1 + ``` + +Now restart Unbound to activate your new configuration: + + ```sh + systemctl restart unbound +```` + +To test to see if your DNS server is resolving, add +`nameserver 127.0.0.1` to your `/etc/resolv.conf`. If you are able to +resolve domains, Unbound is working. + +## Installing DNSS. + +Now we need to install a program to convert HTTP requests to DNS +queries. `dnss` accomplishes that goal very well. + +To install DNSS, run the following command: + +```sh +apt install -y dnss +``` + +### Configuring DNSS. + +DNSS comes with a bad default configuration, disable it using the +following command: + +```sh +systemctl disable --now dnss dnss.socket +``` + +Now, using your favorite text editor, create a new file in +`/etc/systemd/system` named `doh.service`. This will be the new DNSS +configuration file. Add the following values to the file: + +```systemd +[Unit] +Description=DNSS DNS over HTTPS Proxy +[Service] +ExecStart=/usr/bin/dnss \ + -enable_https_to_dns \ + -https_server_addr 127.0.0.1:8080 \ + -insecure_http_server \ + -dns_upstream 127.0.0.1:53 + +Type=simple +Restart=always +User=dnss +Group=dnss + +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +ProtectSystem=full + +[Install] +WantedBy=multi-user.target +``` + +Close the file and enable/start it using the command: + +```sh +systemctl enable --now doh.service +``` + +## Setting up Nginx. + +To set up Nginx with HTTPS, follow [these](/basic/nginx) [guides](/basic/certbot). + +Once you\'ve gotten all of that set up, we\'ll reverse proxy our HTTPS +to DNS proxy. Open up your Nginx config file, and add the following +values: + +```nginx +location /dns-query { + proxy_pass http://127.0.0.1:8080/; +} +``` + +Now, your configuration should look something like this: + +```nginx +server { + listen 80; + server_name chad.thesiah.xyz; + return 301 https://$host$request_uri; +} +server { + listen 443 ssl http2; + server_name chad.thesiah.xyz; + root /var/www/sich; + ssl_certificate /etc/letsencrypt/live/chad.thesiah.xyz/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/chad.thesiah.xyz/privkey.pem; + location /dns-query { + proxy_pass http://127.0.0.1:8080/; + } +} +``` + +Finally, you can check your Nginx config using `nginx -t`, if the check +passes, restart Nginx using the command: + +```sh +systemctl restart nginx +``` + +## Using your DNS over HTTPS server. + +To use your new DNS over HTTPS server, go to your browser\'s settings +and navigate to the \"Network Settings\" area. You should be able to set +a custom secure DNS url. Once set, you can check to see if it\'s working +by attempting to resolve domains, and by testing your browser with +[whatismydnsserver.com](http://www.whatsmydnsserver.com/). + +## Contributor + +[Josiah.](https://ioens.is) diff --git a/content/dnsmasq.md b/content/dnsmasq.md new file mode 100644 index 0000000..89099bc --- /dev/null +++ b/content/dnsmasq.md @@ -0,0 +1,135 @@ +--- +title: "Dnsmasq" +icon: 'dnsmasq.svg' +tags: ['service'] +short_desc: "Host your own DNS server to block ads and social media." +date: 2022-09-13 +--- + +[Dnsmasq](https://dnsmasq.org) is a libre DNS and DHCP system that allows anyone to run a DNS server to resolve domains. +Normally to block domains and ads, users on most operating systems can edit their **`/etc/hosts` file** or use one of the many existing ad-blocking hosts collections available online. +However, if you're trying to block ads **over your entire home network** and do not have access to your router's hosts file, +then setting up your own DNS server can be very advantageous. + +This also comes with the benefit of increased flexibility regarding name resolution; +for example, with Dnsmasq, you can employ the usage of **wildcard domains** to block massive ranges of ads, trackers and entire social media networks. + +## Before we begin... +while Dnsmasq is very versatile software that can be used for a variety of networking and DNS applications, +this guide assumes you only want to setup Dnsmasq to **block domains from resolving** (ie. ads and social media sites). +It is possible to get **custom domain resolution** and **internal network services** running using Dnsmasq, +but this is beyond the scope of this article. + +## Installation +Dnsmasq is available in the Debian repositories: +``` +apt install dnsmasq +``` + +## Configuration +### Basic configuration +By default, Dnsmasq will start a DNS server listening on `localhost:53`. +You can even test this if you have the `bind9` package installed: + +```sh +dig @localhost example.org +``` + +This command should return the A DNS records for `example.org`. + +We can configure Dnsmasq to listen on the public internet by editing its config file, `/etc/dnsmasq.conf`. +In this file, you'll find this line, commented out: + +```sh +#interface= +``` +We need to specify the **interface we wish to listen on** to provide the DNS service. +In most cases (such as when using a Debian VPS) this will simply be `eth0`. +However, please run `ip a` to determine which interface is correct for your system, if you're unsure. + +```sh +interface={{<hl>}}eth0{{</hl>}} +``` + +It's also **highly recommended** to uncomment this following line, +just to prevent Dnsmasq from forwarding requests to local names. +``` +domain-needed +``` + +Now all we have to do is restart Dnsmasq's systemd service: + +```sh +systemctl restart dnsmasq +``` + +And, on our **local machine,** we can try using the `bind9` utilities to test our DNS server: +```sh +dig @{{<hl>}}your_servers_public_ip{{</hl>}} example.org +``` + +This should return the correct A DNS records for `example.org`, like when testing using `localhost`. + +### Changing Authoritative DNS Providers +By default, Dnsmasq will use the DNS servers provided in `/etc/resolv.conf`. +You can change this file directly, altering DNS resolution for your entire system: + +```sh +# Quad9 DNS Server +nameserver {{<hl>}}9.9.9.9{{</hl>}} +nameserver {{<hl>}}149.112.112.112{{</hl>}} +``` + +## Blocking DNS Requests + +### Using a Hostsfile +As mentioned previously, one of Dnsmasq's advantages is that it can read `/etc/hosts` and other host resolution files. +This makes it 100% compatible with existing ad-blocking hosts files. + +```sh +0.0.0.0 www.youtube.com +0.0.0.0 www.reddit.com +``` +This hosts file blocks `www.youtube.com` and `www.reddit.com`. + +To read another hosts file, in addition to `/etc/hosts`, you can use the following in `/etc/dnsmasq`: +```sh +addn-hosts=/etc/hosts.2 +``` + +The only complication is that **every time you update the hosts file, Dnsmasq must be restarted:** + +```sh +systemctl restart dnsmasq +``` + +### Using Dnsmasq's Configuration +For more advanced forms of DNS blocking, such as **domain wildcards,** you can edit `/etc/dnsmasq.conf` directly: + +```sh +address=/{{<hl>}}netflix.com{{</hl>}}/0.0.0.0 +``` +This configuration will block all requests to `netflix.com` and its subdomains. This way you **don't need a massive hosts file** containing every single possible subdomain. All you need to know is the root domain. + +And as usual, remember to restart the Dnsmasq systemd service every time the configuration is altered. +``` +systemctl restart dnsmasq +``` + +## Using Dnsmasq +If you intend to use your new DNS server on your home network, +this is as easy as setting your primary DNS resolver in your router's settings to your **DNS server's public IP address.** + +For example, on a local Linux machine, you could edit `/etc/resolv.conf`: +```sh +nameserver {{<hl>}}your_servers_public_ip{{</hl>}} +``` + +Generally this should be an intuitive process on most router interfaces, +and most OS' will let you edit the DNS in their respective network settings. + +--- + +Written by [Denshi.](https://denshi.org) +Donate Monero at: +`48dnPpGgo8WernVJp5VhvhaX3u9e46NujdYA44u8zuMdETNC5jXiA9S7JoYMM6qRt1ZcKpt1J3RZ3JPuMyXetmbHH7Mnc9C` diff --git a/content/dokuwiki.md b/content/dokuwiki.md new file mode 100644 index 0000000..6f224d0 --- /dev/null +++ b/content/dokuwiki.md @@ -0,0 +1,113 @@ +--- +title: "DokuWiki" +icon: 'dokuwiki.svg' +tags: ['service'] +date: 2023-01-30 +short_desc: 'A simple wiki with clean syntax and no databases.' +--- + +[DokuWiki](https://www.dokuwiki.org) is a simple wiki software, similar to MediaWiki. Unlike MediaWiki, it uses plain text files to store its content, not databases, making it simpler to configure than MediaWiki. It's a good choice if you want a simple wiki engine without all the bells and whistles of MediaWiki and the additional step of setting up databases. + +## Installation + +Although DokuWiki is available on the main debian repos, it is outdated and has a different directory structure, which may lead to problems with plugins and make it harder to follow the official documentation, so we're gonna install it from a tarball. + +First, install the dependencies. + +```sh +apt install nginx php php-fpm php-xml php-mbstring php-zip php-intl php-gd +``` + +Now, get the tarball. + +```sh +wget https://download.dokuwiki.org/src/dokuwiki/dokuwiki-stable.tgz +tar xzvf dokuwiki-stable.tgz +mv dokuwiki-*a /var/www/dokuwiki +chown -R www-data:www-data /var/www/dokuwiki +``` + +## Nginx Configuration + +Create a file named `/etc/nginx/sites-available/dokuwiki` using your favorite text editor and add the following lines, based on the configuration [here](https://www.dokuwiki.org/install:nginx). **Remember to change `wiki.example.org` to your website's name.** Also, pay attention to the lines containing `client_max_body_size`, which determines the maximum file size allowed for uploads, and the first `location` line, because it needs to be commented during the installation and uncommented when it's done. + +```nginx +server { + listen 80; + listen [::]:80; + server_name wiki.example.org; + + # Maximum file upload size is 4MB - change accordingly if needed + client_max_body_size 4M; + client_body_buffer_size 128k; + + root /var/www/dokuwiki; + index doku.php; + + #Remember to comment the below out when you're installing, and uncomment it when done. + #location ~ /(conf/|bin/|inc/|vendor/|install.php) { deny all; } + + #Support for X-Accel-Redirect + location ~ ^/data/ { internal ; } + + location ~ ^/lib.*\.(js|css|gif|png|ico|jpg|jpeg)$ { + expires 365d; + } + + location / { try_files $uri $uri/ @dokuwiki; } + + location @dokuwiki { + # rewrites "doku.php/" out of the URLs if you set the userwrite setting to .htaccess in dokuwiki config page + rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last; + rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last; + rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last; + rewrite ^/(.*) /doku.php?id=$1&$args last; + } + + location ~ \.php$ { + try_files $uri $uri/ /doku.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REDIRECT_STATUS 200; + fastcgi_pass unix:/var/run/php/php-fpm.sock; + # fastcgi_pass unix:/var/run/php5-fpm.sock; #old php version + } +} +``` + +Enable the website. + +```sh +ln -s /etc/nginx/sites-available/dokuwiki /etc/nginx/sites-enabled/ +``` + +Generate a SSL certificate for the subdomain. + +```sh +certbot --nginx +``` + +Restart nginx and php in order for the changes to take effect. + +```sh +systemctl restart nginx && systemctl restart php8.2-fpm +``` + +Finally, go to `wiki.yourwebsite.com/install.php` to finish the installation process. Read up [the documentation](https://www.dokuwiki.org/installer) in order to understand what each of those itens mean. + +Once that's done, remember to uncomment the `location` line on the nginx configuration file. Open `/etc/nginx/sites-available/dokuwiki` with a text editor and remove the "#" symbol at the beginning of the line. + +```nginx +#Remember to comment the below out when you're installing, and uncomment it when done. +location ~ /(conf/|bin/|inc/|vendor/|install.php) { deny all; } +``` + +Reload nginx once again for the changes to take effect. + +```sh +systemctl restart nginx +``` + +Your wiki is now live! Have fun and happy hacking. + +**Contributor** - [Adachi](https://github.com/AdachiWasRight) diff --git a/content/ejabberd.md b/content/ejabberd.md new file mode 100644 index 0000000..eff3b36 --- /dev/null +++ b/content/ejabberd.md @@ -0,0 +1,310 @@ +--- +title: "ejabberd" +date: 2022-03-29 +icon: 'ejabberd.png' +tags: ['service'] +short_desc: "A chat server based on XMPP." +--- + +[Ejabberd](https://ejabberd.im) is a server for the XMPP protocol written in Erlang. It's more scalable, and easier to setup than [Prosody](/prosody) due to having most of its modules built-in and pre-configured by default. + +## Prerequisites + +### Subdomains + +Ejabberd presumes that you have already created all the **required and optional subdomains** for its operation prior to running it. + +Depending on the usecase, you may need any or all of the following domains for XMPP functionality: + +- **example.org** - Your XMPP hostname +- **conference.example.org** - For `mod_muc`, Multi User Chats (MUCs) +- **upload.example.org** - For `mod_http_upload`, file upload support +- **proxy.example.org** - For `mod_proxy65`, SOCKS5 proxy support +- **pubsub.example.org** - For `mod_pubsub`, publish-subscribe support (A fancier RSS) + +Only the **example.org** domain is required for basic, private chat usage. +If you do **not** wish to use a certain domain, just disable it's associated module and ejabberd won't complain when it can't find it's associated certificate. +For example, if you don't want [Publish-Subscribe](https://xmpp.org/extensions/xep-0060.html) support, just comment out the `mod_pubsub` config in `/etc/ejabberd.yml`: + +```yml +## mod_pubsub: +## access_createnode: pubsub_createnode +## plugins: +## - flat +## - pep +## force_node_config: +## ## Avoid buggy clients to make their bookmarks public +## storage:bookmarks: +## access_model: whitelist +``` + +This guide will assume **all these subdomains** have been created. + +#### Custom Subdomains + +If you wish to customize any of these domains, edit `/etc/ejabberd.yml` and under every appropriate module that needs a subdomain, add the following setting: +```yml +mod_muc: + host: {{<hl>}}muc.example.org{{</hl>}} +``` + +## Installation + +To get the latest version of ejabberd, you need to first setup the ejabberd apt repositories: + +```sh +curl -o /etc/apt/sources.list.d/ejabberd.list https://repo.process-one.net/ejabberd.list +curl -o /etc/apt/trusted.gpg.d/ejabberd.gpg https://repo.process-one.net/ejabberd.gpg +``` + +Then update the repositories and install the `ejabberd` package: + +```sh +apt update +apt install ejabberd +``` + +## Configuration + +The ejabberd server is configured in `/etc/ejabberd/ejabberd.yml`. +Changes are only applied by restarting the ejabberd daemon in systemd: + +```sh +systemctl restart ejabberd +``` + +### Hostnames + +The **XMPP hostname** is specified in the `hosts` section of +`ejabberd.yml`: + +```yml +hosts: + - {{<hl>}}example.org{{</hl>}} +``` + +### Certificates + +Unlike [Prosody,](https://prosody.im) ejabberd doesn\'t come equipped +with a script that can automatically copy over the relevant certificates +to a directory where the ejabberd user can read them. + +One way of organizing certificates for ejabberd is to have them stored +in `/etc/ejabberd/certs`, with each domain having a separate directory +for both the fullchain cert and private key. + +Using certbot, this process can be easily automated with these commands: + +```bash +DOMAIN={{<hl>}}example.org{{</hl>}} + +# Set the domain names you want here +declare -a subdomains=("" "conference." "proxy." "pubsub." "upload.") + +for i in "${subdomains[@]}"; do + certbot --nginx -d $i$DOMAIN certonly + mkdir -p /etc/ejabberd/certs/$i$DOMAIN + cp /etc/letsencrypt/live/$i$DOMAIN/fullchain.pem /etc/ejabberd/certs/$i$DOMAIN + cp /etc/letsencrypt/live/$i$DOMAIN/privkey.pem /etc/ejabberd/certs/$i$DOMAIN +done +``` +*Note: Just like with Prosody, you might want to write this script to a file and setup a [cronjob](/cron) to run it periodically. This should help prevent your certificates from expiring.* + +Make sure all the certificates are readable by the `ejabberd` user: +```sh +chown -R ejabberd:ejabberd /etc/ejabberd/certs +``` + +To enable the use of all these certificates in ejabberd, the following +configuration is necessary: + +```yml +certfiles: + - "/etc/ejabberd/certs/*/*.pem" +``` + +### Admin User + +The **admin user** can be specified in `ejabberd.yml` under the `acl` +section: + +```yml +acl: + admin: + user: admin +``` + +This would make **admin@example.org** the user with administrator +privileges. + +### File Uploads + +To ensure full compliance with XMPP standards, add the following configuration to `mod_http_upload`: + +```yaml +mod_http_upload: + put_url: https://@HOST@:5443/upload + docroot: {{<hl>}}/var/www/upload{{</hl>}} + custom_headers: + "Access-Control-Allow-Origin": "https://@HOST@" + "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS" + "Access-Control-Allow-Headers": "Content-Type" +``` + +Make sure to create and give the `ejabberd` user ownership of `/var/www/upload` or any other directory you choose to use for file uploads: + +```sh +chown -R ejabberd:ejabberd /var/www/upload +``` + +### Message Archives + +The ejabberd server supports keeping archives of messages through its `mod_mam` module. This can be enabled by uncommenting the following lines: + +```yml +mod_mam: + assume_mam_usage: true + default: always +``` + +## Database + +### Why use a database? + +We can find the following comment in the `mod_mam` section of `/etc/ejabberd.yml`: + +```yml +mod_mam: + ## Mnesia is limited to 2GB, better to use an SQL backend + ## For small servers SQLite is a good fit and is very easy + ## to configure. Uncomment this when you have SQL configured: + ## db_type: sql +``` + +As these comments imply, an **SQL backend** is strongly recommended if you wish to use your ejabberd server for anything more than just testing. Ejabberd supports **MySQL, SQLite** and **PostgreSQL.** For the purpose of efficiency, this guide will use **PostgresSQL** because other server software like [Matrix](/matrix) and [PeerTube](/peertube) support it. + +### Installing PostgreSQL + +PostgreSQL is available in the Debian repositories: + +```sh +apt install postgresql +``` + +In addition, you will have to install the **appropriate headers for Erlang,** the language ejabberd is written in, so it can actually interact with the PostgreSQL server: +```sh +apt install erlang-p1-pgsql +``` + +Start the PostgreSQL daemon to begin using it: + +```sh +systemctl start postgresql +``` + +### Creating the Database + +To create the database, first create a PostgreSQL user for ejabberd: + +```sh +su -c "createuser --pwprompt ejabberd" postgres +``` + +Then, create the database and make `ejabberd` its owner: + +```sh +su -c "psql -c 'CREATE DATABASE ejabberd OWNER ejabberd;'" postgres +``` + +### Importing Database Scheme + +Ejabberd does **not** create the database scheme by default; It has to be imported into the database before use. + +```sh +su -c "curl -s https://raw.githubusercontent.com/processone/ejabberd/master/sql/pg.sql | psql ejabberd" postgres +``` + +### Configuring ejabberd to use PostgreSQL + +Finally, add the following configuration to `ejabberd.yml`: + +```yml +sql_type: pgsql +sql_server: "localhost" +sql_database: "{{<hl>}}ejabberd{{</hl>}}" +sql_username: "{{<hl>}}ejabberd{{</hl>}}" +sql_password: "{{<hl>}}psql_password{{</hl>}}" + +default_db: sql +``` +That line at the end sets **every module's database** to default to the `sql` backend. This includes the `mod_mam` module, so all our data is being stored with PostgreSQL. + +### Voice and Video Calls + +Ejabberd supports the **TURN** and **STUN** protocols to allow internet users behind NATs to perform voice and video calls with other XMPP users. **This is enabled by default using [ejabberd_stun](https://docs.ejabberd.im/admin/configuration/listen#ejabberd-stun-1).** + +**However,** if you plan on running ejabberd alongside **other applications** that require TURN and STUN, such as Matrix, then you'll have to setup your own external TURN server using Coturn. + +#### Setup with Coturn and `mod_stun_disco` + +Firstly, setup a TURN and STUN server with [Coturn,](/coturn) using an **authentication secret.** + +Then, edit `mod_stun_disco` to contain the appropriate information for +your turnserver: + +```yml + mod_stun_disco: + secret: "{{<hl>}}your_auth_secret{{</hl>}}" + services: + - + host: {{<hl>}}turn.example.org{{</hl>}} + type: stun + - + host: {{<hl>}}turn.example.org{{</hl>}} + type: turn +``` + + +## Using ejabberd + +### Registering the Admin User + +To begin using ejabberd, firstly start the ejabberd daemon: + +```sh +systemctl restart ejabberd +``` + +Then, using `ejabberdctl` as the ejabberd user, register the admin user which is set in `ejabberd.yml`: + +```sh +su -c "ejabberdctl register {{<hl>}}admin example.org password{{</hl>}}" ejabberd +``` + +This will create the user **admin@example.org.** + +### Using the Web Interface + +By default, ejabberd has a web interface accessible from **http://example.org:5280/admin**. When accessing this interface, you will be prompted for the admin credentials: + +{{< img src="/pix/ejabberd-login.webp" >}} + +After signing in with the admin credentials, you will be able to manage +your ejabberd server from this web interface: + +{{< img src="/pix/ejabberd-admin.webp" >}} + +## Further Configuration + +For a deeper look into all the modules and options, have a look at the following ejabberd documentation: +- Ejabberd's [Listen Modules](https://docs.ejabberd.im/admin/configuration/listen/) and [Listen Options](https://docs.ejabberd.im/admin/configuration/listen-options/) +- Ejabberd's [Top-Level Options](https://docs.ejabberd.im/admin/configuration/toplevel/) +- Ejabberd's [Modules' Options](https://docs.ejabberd.im/admin/configuration/modules/) + +*And with that, you've successfully setup your ejabberd XMPP server!* + +--- + +Written by [Denshi.](https://denshi.org) +Donate Monero at: +`48dnPpGgo8WernVJp5VhvhaX3u9e46NujdYA44u8zuMdETNC5jXiA9S7JoYMM6qRt1ZcKpt1J3RZ3JPuMyXetmbHH7Mnc9C` diff --git a/content/federation.md b/content/federation.md new file mode 100644 index 0000000..2215d6b --- /dev/null +++ b/content/federation.md @@ -0,0 +1,58 @@ +--- +title: "Federation" +draft: true +tags: ["concepts", "activity-pub"] +--- + +The internet was supposed to be a place where everyone was an internet +SiCh. Everyone had their own website and email and own services. +Obviously, this site is all about getting back to that ideal. + +That\'s why it\'s important to understand the concept of +<dfn>Federation</dfn> in technology. It\'s the idea that instead of one +central \"node\" or site that everyone uses, like Facebook, Twitter, +Insta, R\*ddit, people can run their own sites that can nonetheless +_interact_ with othersites as easily as if they were the same. + +You already know one federated technology: email. There is no one site +for email, but many sites, and all people on all those sites can use +email to talk to one another. You can get censored on Facebook. You +can\'t get censored on \"email.\" You could have a Gmail account +deleted, but you are not blocked out of the system, as you can go to any +number of sites and get a new account or [make your own server](/email) and you can still talk to all your friends via +email. + +## \"Federated\" Social Media + +The idea of Federated Social Media is using that principle used in +email, but for other things, like chatting or social media. + +Here\'s an example. There is some software [you can install on your +server](/pleroma) called [Pleroma](https://pleroma.social/). It can +be installed on your site just like a web or email server, but what it +does is creates a Twitter-like microblogging site. You can then have +your friends join and use it just like you use Twitter, with you as the +admin and deciding policy and you can even format and decorate the site +how you want. + +### It gets even better\... + +**But here is the clincher.** Federated social media like Pleroma can +interact with other Pleroma servers on the internet in the same way that +Gmail\'s servers can send messages to any other email server. So you +might have 2 people on your Pleroma site, but you can interact with the +many thousands of other Pleroma sites. + +There is seamless interaction. You can view, like, share and respond to +their posts as if they were part of your own site. + +### And it gets even betterer\... + +Pleroma is based on a protocol called [Activity +Pub](https://activitypub.rocks/). This is also used by other software +like [PeerTube](https://joinpeertube.org/) (which is a self-hosted +YouTube-equivalent), [Friendica](https://friendi.ca/) (Facebook +equivalent). + +Accounts on _all_ of these platforms can view, interact with and participate with accounts on other platforms. +You can do the equivalent of posting a comment on a "YouTube" video from your "Twitter" account. diff --git a/content/fosspay.md b/content/fosspay.md new file mode 100644 index 0000000..6c1f251 --- /dev/null +++ b/content/fosspay.md @@ -0,0 +1,183 @@ +--- +title: "Fosspay" +tags: ['service'] +icon: 'devault.jpg' +short_desc: "A self-hosted payment and donation gateway interfaced with Stripe." +date: 2022-06-30 +--- + +[Fosspay](https://sr.ht/~sircmpwn/fosspay/) is a free-software web frontend for receiving donations and +subscriptions, similar to Patreon or Liberapay, but which can be hosted +on your own server. It can also interface with Patreon or Github +Sponsors to aggregate all your donations. + +## Stripe Setup + +Fosspay uses [Stripe](https://stripe.com) as a payment processor. You first must go to [their website](https://stripe.com) and create an account. + +Once you set everything up, you can go to [https://dashboard.stripe.com/account/apikeys](https://dashboard.stripe.com/account/apikeys) and get your "Publishable Key" and "Secret Key" which will be all you need to set up Fosspay. + +<aside> + +### Note on Free Software + +Stripe is perhaps the best way to transact in the legacy financial system +online, but you are still not using free and privacy respecting software. +Fosspay is an open source payment gateway, but it still connects to Stripe. +The only way to transact value over the internet on all free software is +[crypto-currency](/monero/). + +</aside> + +## Dependencies + +We will need git, postgres and the ability to make a python virtual +environment: + +```sh +apt install git python3-venv python3-dev postgresql libpq-dev +``` + +## Download and Installation + +We will download fosspay to `/var/www/fosspay/`. This directory will +also serve as our virtual environement. + +```sh +git clone https://git.sr.ht/~sircmpwn/fosspay /var/www/fosspay +python3 -m venv /var/www/fosspay +``` + +Activate the python environment with the command below, then we will +install the dependencies. + +```sh +source /var/www/fosspay/bin/activate +cd /var/www/fosspay +pip install -r requirements.txt +``` + +Be sure you are still in `/var/www/fosspay`, then we will build the +package and create the configuration file. + +```sh +make +cp config.ini.example config.ini +``` + +## Create a Database + +Fosspay uses a PostgreSQL database to store donation information, so +let\'s create a database and user for it. + +First, become the `postgres` user and run the `psql` command: + +```sh +su postgres +psql +``` + +We will create a database named `fosspay` controled by a user named +`fosspay` (also identified by a a password `fosspay`). + +```sql +create database fosspay ; +create user fosspay with encrypted password 'fosspay' ; +grant all privileges on database fosspay to fosspay ; +\q +``` + +Note that if you want to use a different username or password for +whatever reason, change them in the command above, but also in the +`connection-string` variable in the configuration file. + +## Configuration + +Now open up `/var/www/fosspay/config.ini` and we will set things up. +Here are a list of things to edit. + +- `domain` should be set to `{{<hl>}}donate.example.org{{</hl>}}`, with your domain. +- `protocol` can be set to `https`. +- Get or create an email account to use as a mailer and add the account/server + information to the email settings. +- Add your public and secret Stripe keys to the information. +- Change the `connection-string` to + `postgresql://fosspay:fosspay@localhost/fosspay` as set up above. + +**An important note:** mail ports *must* be opened on the server you\'re using, +or else Fosspay will silently fail to send mails when someone tries to donate +or reset their password. You do not have to run a mail server on the same +server as Fosspay, but either way, mail submission ports must be opened. This +usually requires contacting your VPS provider and requesting it from them. +Aside from this, any error in the email setup will cause Fosspay to crash +silently. + +### Optional Integration with Patreon, Github, Liberapay + +Note that if you have a previous Patreon, Github Sponsors or Liberapay +account, you can create an access token for Fosspay, so that you can +display your income from those sources along side Fosspay monthly +donations. + +For Liberapay, you only need to include your username. You must create a +[Github access token](https://github.com/settings/tokens) with the +\"user\" access to interface with it, and you have to add several +[Patreon client +parameters](https://www.patreon.com/portal/registration/register-clients) +for it. + +## Nginx configuration + +Fosspay runs on port 5000, so we can have Nginx show the site. Create an +Nginx configuration file modeled as below: + +```nginx +server { + listen 80 ; + listen [::]:80 ; + server_name {{<hl>}}donate.example.org{{</hl>}} ; + location / { + proxy_pass http://localhost:5000 ; + } +} +``` + +After that, [remember to get HTTPS for the subdomain!](/basic/certbot) +HTTPS is absolutely required for using Stripe as a payment processor. + +## Systemd File + +We can now create a systemd service file for Fosspay. Create a file in +`/etc/systemd/system/fosspay.service` as below: + +```systemd +[Unit] +Description=fosspay website +Wants=network.target +Wants=postgresql.target +Before=network.target +Before=postgresql.target +[Service] +Type=simple +WorkingDirectory=/var/www/fosspay +VIRTUAL_ENV=/var/www/fosspay +Environment=PATH=$VIRTUAL_ENV/bin:$PATH +ExecStart=/var/www/fosspay/bin/gunicorn app:app -b 127.0.0.1:5000 +ExecStop=/var/www/fosspay/bin/gunicorn +[Install] +WantedBy=multi-user.target +``` + +Note that for safety, we are running fosspay through `gunicorn` in our +virtual environment. + +We can now run `systemctl start fosspay` to start the service, and it +should appear at the URL you designated above. + +## Customizing the Page + +Within `/var/www/fosspay/templates`, there are various files that you +can change to add text and other features to the page. The main file is +`summary.html`, where you can add a description and other information +that will appear. Restart the service after updating files to make +changes live. diff --git a/content/gemini.md b/content/gemini.md new file mode 100644 index 0000000..ace0503 --- /dev/null +++ b/content/gemini.md @@ -0,0 +1,189 @@ +--- +title: "Gemini" +date: 2021-07-01 +tags: ['server'] +short_desc: "A minimalist alternative to HTTP with a modern twist." +--- +## What is Gemini? {#whatis} + +[Gemini](https://gemini.circumlunar.space) is a new +internet protocol which is different from the HTTP and Gopher. It\'s +much cleaner and has a growing community and audience of hackers. + +### Why use gemini protocol? + +- Gemini capsules (webpages of gemini) are lightweight, minimal, and + don\'t use many resources to operate. +- It can run along with your websites. Gemini capsules use port 1965 + by default. Your webserver can run at port 80 or 443 along with + gemini server at port 1965. +- By exploring an alternative protocol, you can check different ways + to serve data and blogs. + +To access any gemini urls i.e. `gemini://example.org`, you can use any +gemini client such as +[amfora](https://github.com/makeworld-the-better-one/amfora), +[lagrange](https://gmi.skyjake.fi/lagrange), +[elpher](https://thelambdalab.xyz/elpher/), etc. + +## Instructions + +### Create a gemini user + +It is most secure and clean to have a separate `gemini` user, so let\'s +create one: + +```sh +useradd -m -s /bin/bash gemini +``` + +Now log in as `gemini` with the following command: + +```sh +su -l gemini +``` + +To create and serve a gemini capsule, we need three basic steps: + +1. Content -- the webpages in our capsule +2. TLS certificate -- Gemini requires encrypted connection. +3. Gemini server -- the program that makes our capsule available + (similar to Nginx for HTTP) + +As the gemini user, we can create three different directories to +simplify the process: + +```sh +mkdir -p ~/gemini/{content,certificate,server} +``` + +### Content + +This will be the directory where your capsule files will be contained. +Gemini uses text/gemini markup (in place of HTTP\'s equivalent HTML). It +heavily borrows from Markdown. Similar to .html or .md, gemini uses .gmi +as its extension. + +To create one gemini file, go inside the `content` directory and create +one `index.gmi` file. + +```sh +nano gemini/content/index.gmi +``` + +We can add the content we want in our Gemini capsule here: + +```yaml +# This is Sample Gemini page +## With header 1 and header 2 +And a short paragraph like this. +=> /index.gmi Link to the same page +``` + +### TLS certificate + +Go to the `certificate` directory which we created earlier and generate +a TLS certificate using OpenSSL. + +```sh +cd ~/gemini/certificate/ +openssl req -new -subj "/CN=example.org" -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -days 3650 -nodes -out cert.pem -keyout key.pem +``` + +### Gemini server + +#### Download and prepare the server + +There are [many gemini server software choices +available](https://gemini.circumlunar.space/software). We will use +`agate` server for now. This is a simple gemini server written in Rust. + +It\'s a good idea to always get the most recent version, which you can +see [on the agate releases +page](https://github.com/mbrubeck/agate/releases). At the time of this +writing, that is agate v3.1.0 which we will now download. We will +download it to the `server` directory we made. + +```sh +cd ~/gemini/server +wget https://github.com/mbrubeck/agate/releases/download/v3.1.0/agate.x86_64-unknown-linux-gnu.gz +``` + +Unzip the gz, then rename and make it executable: + +```sh +gunzip agate.x86_64-unknown-linux-gnu.gz +mv agate.x86_64-unknown-linux-gnu agate-server +chmod +x agate-server +``` + +#### Create a system service + +Now we need to create a systemd service to autostart and manage agate. +The gemini user does not have permission to do this, so press <kbd>ctrl-d</kbd> +to log out of the gemini user and return to root. As root, create the +file below by opening it in your text editor (nano, vim, etc.): + +```sh +nano /etc/systemd/system/agate.service +``` + +Add the following content to the file **customizing highlighted text** +to your use. + +```systemd +[Unit] +Description=agate +After=network.target + +[Service] +User=gemini +Type=simple +ExecStart=/home/gemini/gemini/server/agate-server --content /home/gemini/gemini/content --certs /home/gemini/gemini/certificate/ --hostname example.org --lang en-US + +[Install] +WantedBy=default.target +``` + +Now we are ready to run server. Enable and run agate server. + +```sh +systemctl enable agate +systemctl start agate +``` + +#### Firewall + +Lastly, if you have a firewall running, remember to open port 1965, +which is the port number used by gemini: + +```sh +ufw allow 1965 +``` + +## Finalization + +Now your server should be running. If everything went okay, you can +access your gemini capsule via any gemini client with a url like this: + +```txt +gemini://example.org +``` + +Sample gemini site for reference: + +```txt +gemini://gemini.circumlunar.space +``` + +Enjoy your first gemini capsule. + +For information about how to write in \"gemtext\" the markup language in +Gemini, see this site: +<https://gemini.circumlunar.space/docs/gemtext.gmi>. As you might guess, +it also has an analogous gemini capsule here: +gemini://gemini.circumlunar.space/docs/gemtext.gmi + +------------------------------------------------------------------------ + +*Written by [nihar.page](https://nihar.page)* diff --git a/content/git.md b/content/git.md new file mode 100644 index 0000000..814caf3 --- /dev/null +++ b/content/git.md @@ -0,0 +1,131 @@ +--- +title: "Git Server" +date: 2020-07-01 +icon: "git.svg" +tags: ["service"] +short_desc: "Hosting your own basic git server." +--- + +Once you have your own VPS or other Internet-available server, you can +start hosting your own git repositories. The goal of this tutorial is +for you to go from + +```sh +git clone github.com/... +``` + +to + +```sh +git clone YourSiChDomainName.xyz/... +``` + +so you can cultivate your own homegrown, grass-fed code, rather than +relying on a centralized proprietary service like GitHub. + +## Installing git + +You most likely already have it installed on your server, but if not, +run: + +```sh +apt install git +``` + +We don\'t need any additional software, `git` itself ships with +everything needed to host a remote repository! + +## Creating a git user + +To prevent exploiting your system, services should usually be run under another +user that can only affect the relevant parts of the server. Let's create a user +for git. + +```sh +useradd -m git -d /var/git -s /bin/bash +``` + +The `git` user's home directory will be `/var/git` and we also set the default +user shell as bash instead of sh for ease when on the command line. + +### Become the git user and create the directory + +If you\'re logged in to your server as root and have `git` installed, +you can become the `git` user by executing + +```sh +su -l git +``` + +The `-l` option should put us in `git`'s home directory, but you can `cd +/var/git` otherwise. + +### Create the repo + +Now you can create the bare repository with + +```sh +git init --bare {{<hl>}}my-repo.git{{</hl>}} +``` + +By convention, bare repository names end with \".git\". (A bare repository is +just one without the file index, (i.e. the familiar browseable file structure).) + +Repeat the above command for any other repositories you want to host. + +## Syncing local repositories with your server + +### Set up SSH login for the git user + +Git uses SSH to connect to a server, and we will definitely want to use an SSH +key pair that we authorized. This is not only most secure, but also easiest +since we don't need to put in our password whenever we pull or push. + +There is a brief article [on setting up SSH keys](/sshkeys). We need to do +exactly that, but for the `git` user, instead of the default `root` user. Note +that if you want to upload your SSH key directly to the git user as in that +tutorial, remember to run `passwd git` to give the git user a password so you +can log in. + +If you've already set up password-less SSH log-ins for root (and disabled SSH +password authentication), you can run the following commands as root, which +will copy over your authorized key to the git user as well. + +```sh +mkdir /var/git/.ssh # Create the required directory. +cp ~/.ssh/authorized_keys /var/git/.ssh/ # Copy over the authorized key. +chown git:git -R /var/git/.ssh # Make the created directory and contents to be owned by the git user. + +``` + +### Syncing a new repository with your server + +Now that we've set that up, we can push a repository we have on our computer to +that newly created bare repo. First, on our local computer, we run a command like this: + +```sh +git remote add origin git@{{<hl>}}example.org{{</hl>}}:{{<hl>}}my-repo.git{{</hl>}} +``` + +Note some of the things you will change: + +- `example.org`, obviously is a stand-in for your domain name. +- `my-repo.git` is the name of the repository, but it is also the relative location of it. Since it is in the `git` user's home directory, we don't need anything else, but if you decide to put a git repository elsewhere---like in `/var/www/git/stuff.git`, you can provide that absolute file location instead. +- `origin` is a unique name for your remote repository. Since "origin" is probably already used if you are using Github or another service, you'll want to change this to whatever you want. Could be `myserver` or `vps` or `own`, as long as it is unique. + +Once you run that command successfully to add a new remote repository, and also assuming you change `origin` to let's say the more unique `personal`, you can push your local git server as expected: + +```sh +git push {{<hl>}}personal{{</hl>}} master +``` + +That's all a git server is! Very simple. + +If you want a minimalist front-end to a git server, follow our guide on [cgit](/cgit)! + +If you want a large and user-friendly Github-like site for your git projects, follow our guide on [Gitea](/gitea)! + +## Contribution + +- Martin Chrzanowski \-- [website](https://m-chrzan.xyz), [donate](https://m-chrzan.xyz/donate.html) +- Edits and fixes by Luke. diff --git a/content/gitea.md b/content/gitea.md new file mode 100644 index 0000000..8fbf3e8 --- /dev/null +++ b/content/gitea.md @@ -0,0 +1,161 @@ +--- +title: "Gitea" +date: 2020-07-02 +icon: 'gitea.svg' +tags: ['service'] +short_desc: "A fully-featured Github-like git website for serious software projects and communities." +--- + +Gitea allows you to self-host your git repositories similar to [bare +repositories](/git), but comes with additional features that you might know +from GitHub, such as issues, pull requests or multiple users. Its advantage +over GitLab---another Free Software GitHub clone---is that it is much more +lightweight and easier to setup. + +Head over to [gitea.com](https://gitea.com) to see what it looks like in +practice. + +Although Gitea is lighter than Gitlab, if you have a VPS with only 512MB of +RAM, you will probably have to upgrade. Gitea is more memory-intensive than +having just a bare git repository. If you just want a minimalist browseable git +server without issue tracking and pull requests, install [cgit](/cgit) +instead. + +## Installing Gitea + +First install a few dependencies: + +```sh +apt install curl sqlite3 +``` + +Unfortunately, Gitea itself is not in the official Debian repos, so we +will add a third-party repository for it. + +Add the repo\'s gpg key to apt\'s trusted keys: + +```sh +curl -sL -o /etc/apt/trusted.gpg.d/morph027-gitea.asc https://packaging.gitlab.io/gitea/gpg.key +``` + +Then add the actual repository to apt: + +```sh +echo "deb [arch=$(dpkg --print-architecture)] https://packaging.gitlab.io/gitea gitea main" > /etc/apt/sources.list.d/morph027-gitea.list +``` + +Now we can install Gitea: + +```sh +apt update +apt install gitea +``` + +Since apt automatically enables and starts the Gitea service, it should +already be running on port `3000` on your server! + +## Setting up a Nginx reverse proxy + +You should know how to generate SSL certificates and use Nginx by now. +Add this to your Nginx config to proxy requests made to your git +subdomain to Gitea running on port 3000: + +```nginx +server { + listen 443 ssl; + listen [::]:443 ssl; + ssl_certificate /etc/ssl/nginx/{{<hl>}}git.example.org{{</hl>}}.crt; + ssl_certificate_key /etc/ssl/nginx/{{<hl>}}git.example.org{{</hl>}}.key; + server_name {{<hl>}}git.example.org{{</hl>}}; + location / { + proxy_pass http://localhost:3000/; # The / is important! + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + + +And reload Nginx: + +```sh +systemctl reload nginx +``` + +## Setting up Gitea + +If everything worked fine you should now see a setup screen when you go +to your configured domain in the browser. The options should be pretty +self-explanatory, it is only important to select SQLite3 and to replace +the base url and SSH server domain with your own. + +Database Type: +: SQLite3 + +SSH Server Domain: +: **git.example.org** + +Gitea Base URL: +: **git.example.org** + +These and other settings can be changed in a configuration file later so +don\'t worry about making wrong decisions right now. + +After clicking the install button you should now be able to log into +your Gitea instance with the account you just created! Explore the +settings for more things to do, such as setting up your SSH keys. + +If Gitea does not load fully and has random errors, it is possible that +you need to increase your available memory on your VPS. This can usually +be done on your VPS-provider\'s website without too much trouble. + +## A few extras + +### Automatically create a new repo on push + +This is an incredibly useful feature for me. Open up +`/etc/gitea/app.ini` and add `DEFAULT_PUSH_CREATE_PRIVATE = true` to the +`repository` section like so: + +```systemd +[repository] +ROOT = /var/lib/gitea/data/gitea-repositories +DEFAULT_PUSH_CREATE_PRIVATE = true +``` + +If you now add a remote to a repository like this + +```sh +git remote add origin 'ssh://gitea@{{<hl>}}git.example.org{{</hl>}}/username/coolproject.git' +``` + +and push, Gitea will automatically create a private `coolproject` +repository in your account! + +### Change tab-width + +By default Gitea displays tabs 8 spaces wide, however I prefer 4 spaces. +We can change this! + +```sh +mkdir -p /var/lib/gitea/custom/templates/custom/ +``` + +And write this into +`/var/lib/gitea/custom/templates/custom/header.tmpl`: + +```css +<style> +.tab-size-8 { +tab-size: 4 !important; +-moz-tab-size: 4 !important; +} +</style> +``` + +## Contribution + +- [phire](https://phire.cc) diff --git a/content/html.md b/content/html.md new file mode 100644 index 0000000..3da7c53 --- /dev/null +++ b/content/html.md @@ -0,0 +1,143 @@ +--- +title: "Make a Simple Webpage" +draft: true +--- +We now have a webpage that\'s actually on the real-live internet! +You\'ve already made it! Now the only issue is putting what you want on +your website. + +In this little series, we\'ll overview the basics of HTML and CSS, the +two important languages that will allow you to make a stylish multi-page +website. We will start with HTML. + +## HTML + +HTML is the **h**yper**t**ext **m**arkup **l**anguage. It is the +\"language\" that all webpages are written in so that all browsers can +read and display them properly. + +A <dfn>markup language</dfn> is *not* the same as a programming language: +Programming languages specify orders for a computer, while markup +languages are ways of specifying the styling of text. Markup languages +are necessary because computers run on mere text, not colors, sizes, +headers and other styling things. + +Let\'s understand what HTML is. In [a previous article](/basic/nginx), we +put this text in your website\'s `index.html`. + +### Paragraphs + +Note how this HTML file appears as a webpage: + ++-----------------------------------+-----------------------------------+ +| <!DOCTYPE html> |  | +| <p>This is my web | | +| site. Thanks for stopping by!</p> | | +| | | +| <p>Now my website is live!</p> | | ++-----------------------------------+-----------------------------------+ + +The content between the `<p>` and `</p>` tag(s) is formatted as +different paragraphs. If you don\'t use these `<p>` tags, the text will +not be formatted as separate paragraphs even if you write it as multiple +lines. Observe if we add lines to the end of this file: + ++-----------------------------------+-----------------------------------+ +| <!DOCTYPE html> |  | +| <h1>My website!</h1> | | +| <p>This is my web | | +| site. Thanks for stopping by!</p> | | +| | | +| <p>Now my website is live!</p> | | +| Here is some more text. | | +| There are | | +| no paragraph tags on this stuff. | | +| So it | | +| will all appear as one paragraph. | | +| | | +| Despite being on multiple lines. | | +| | | +| | | +| Even this! | | ++-----------------------------------+-----------------------------------+ + +This will seem strange at first, but this is the use of HTML as a markup +language: it allows you to style your document with tags and write it in +whatever way is convenient. + +Let\'s learn more about what HTML can do. + +### Headings + +In addition to paragraphs (`<p>`), we can specify headings with inside +`<h1></h1>` tags. Heading tags are for your page\'s title and section +headings in the document: + +- `<h1></h1>` -- Main and largest headings +- `<h2></h2>` -- Subheadings (smaller) +- `<h3></h3>` -- Sub-subheadings (yet smaller) +- `<h4></h4>` -- Etc., etc. + ++-----------------------------------+-----------------------------------+ +| <h1> |  | +| | | +| <p | | +| >Here is some paragraph text.</p> | | +| | | +| | | +| <p>And here is some more...</p> | | +| | | +| < | | +| h2>This is a subheading (h2)</h2> | | +| | | +| <p>And another paragraph.</p> | | +| | | +| <h2>And here is ano | | +| ther subheading (Also an h2)</h2> | | +| | | +| <p>Etc. etc...</p> | | ++-----------------------------------+-----------------------------------+ + +#### A preview to CSS + +It is very important to use headings like this for your pages. Notice +that on this website, headings come in different colors, text-alignment +and sizes for emphasis. If we use these heading tags, when we clear CSS, +we can easily style all `<h2>`, for example, to be the size and color +and alignment we want. + +## Text formatting + +HTML can also be used to do text formatting. We can make bold, italic, +underlined or struck through text with more HTML tags: + ++-----------------------------------+-----------------------------------+ +| |  | +| | | +| < | | +| p>This is <i>italic text</i>.</p> | | +| | | +| | | +| <p>This is <u>underlined</u>.</p> | | +| | | +| <p>T | | +| his is <s>struck through</s>.</p> | | ++-----------------------------------+-----------------------------------+ + +## Semantic Tags + +While `<b></b>` and `<i></i>` do exist, it\'s actually better *not* to +use them directly in text. + +Try using `<strong></strong>` instead of `<b></b>` and `<em></em>` +instead of `<i></i>`. By default, they will look exactly the same. You +complain that they require more key presses, but it\'s thought to be a +very bad idea to modify lower-level tags with CSS directly. + +Note that some bold words on this site have **different color for +emphasis**. This is a setting set via CSS for all `<strong>` tags. It +would not be a good idea for us to use this for `<b>`, since there might +be a non-colored situation we want to occasionally use it in. diff --git a/content/html2.md b/content/html2.md new file mode 100644 index 0000000..9865e88 --- /dev/null +++ b/content/html2.md @@ -0,0 +1,7 @@ +--- +title: "Images and Links in HTML" +draft: true +--- +## Links + +We need to create links diff --git a/content/html4.md b/content/html4.md new file mode 100644 index 0000000..adb8eb3 --- /dev/null +++ b/content/html4.md @@ -0,0 +1,32 @@ +--- +title: "Doing HTML Right" +draft: true +--- +We\'ve noted that HTML is very forgiving + +## A look at a decent template + +I have a template file that I use for this website that includes all the +basics. When I make a new page, I just copy the template and add the +content. Here is what the template looks like: + +`` + + <!DOCTYPE html> + <html lang=en> + <head> + <title>Your page title</title> + <meta charset="utf-8"/> + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" /> + <link rel='stylesheet' type='text/css' href='style.css'> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel='alternate' type='application/rss+xml' title='Site Title RSS' href='/rss.xml'> + </head> + <body> + <header><h1>Your page title</h1></header> + + <nav></nav> + + <main> + + Put all your page content here in the <main> tag. diff --git a/content/i2p.md b/content/i2p.md new file mode 100644 index 0000000..8dcb7cb --- /dev/null +++ b/content/i2p.md @@ -0,0 +1,145 @@ +--- +title: "i2p" +date: 2021-07-01 +img: 'i2p.svg' +icon: 'itoopie.svg' +tags: ['service'] +short_desc: "A private and uncensorable web-layer similar to Tor." +--- + +Now you have a website, why not offer it in a private alternative such as the Invisible Internet? + +## Setting up I2P + +There are 2 main I2P implementations, I2P and i2pd, we are using i2pd in this guide because it's easier to use on servers. + +### Installing I2P + +We need to [add the i2pd repos to our system](https://repo.i2pd.xyz/) to get the latest version of i2pd: + +Install apt-transport-https and gpg package: + +```sh +apt install apt-transport-https gpg +``` + +Automatically add the repository with a script: + +```sh +wget -q -O - https://repo.i2pd.xyz/.help/add_repo | bash -s - +``` + +After that you can install i2pd as any other software package: + +```sh +apt update +apt install i2pd +``` + +### Enabling I2P + +Next we have to configure the i2pd daemon, the configuration is located at `/etc/i2pd/`. + +Edit the `tunnels.conf` file and add the following configuration to the file: + +```systemd +[example] +type = http +host = 127.0.0.1 +port = 8080 +keys = example.dat +``` + +You can comment or remove the tunnels that are added by default in the configuration file. + +#### Optional: Generating a Vanity Address + +If you run `i2pd` with the configuration above, it will generate a random private key (`example.dat`) for your website at `/var/lib/i2pd/` with a matching address made up of 52 random characters, derived from this same key. + +If you instead pre-generate a private key for your website, you can use brute-force computation to make a "vanity" address, such as the following: +``` +{{<hl>}}chad{{</hl>}}aor3jc08ht340c30mg5cf340j395gj095kuazj5tokipr34f.32.i2p +``` + +To accomplish this, a set of tools named `i2pd-tools` can be installed. + +Begin by cloning their repository: +```sh +git clone --recursive https://github.com/purplei2p/i2pd-tools +``` + +The repository comes with a dependency installation script included. Run this to list the compilation dependencies you'll need, and install them: +```sh +cd i2pd-tools +sh dependencies.sh +``` + +Then compile using the `make` command: +```sh +make +``` + +This will build a variety of useful tools for i2p, with `vain` being the command of interest to generate an address: +```sh +./vain {{<hl>}}chad{{</hl>}} +``` +This command will begin running and output a new set of private keys named `private.dat` to the same directory it's ran from. Copy this file to your i2p configuration and you'll have your vanity address: + +```sh +cp private.dat /var/lib/i2pd/example.dat +``` + +#### Optional: Authentication Strings for Registrars + +I2P has various **registrars** that let users link their long I2P addresses to shorter, more memorable ones, like `example.i2p`. To actually register your site on one of these registrars, you will need an **authentication string.** Luckily, `i2pd-tools` includes such a tool in their repository: + +```sh +./regaddr private.dat {{<hl>}}example.2ip{{</hl>}} > {{<hl>}}auth_string.txt{{</hl>}} +``` + +The command above will save the string to a file named `auth_string.txt`. You will have to place the text contained in that file on a registration page like [http://reg.i2p/add](http://reg.i2p/add) or [http://stats.i2p/i2p/addkey.html](http://stats.i2p/i2p/addkey.html). + +### Getting your I2P Hostname + +Then, run the command `systemctl start i2pd` to start i2pd and `systemctl enable i2pd` to enable i2pd at startup, this will automatically generate our I2P hostname which we will now see. + +This can be done in lynx or a command-line browser by going to `http://127.0.0.1:7070/?page=i2p_tunnels` to get your I2P hostname. + +You can also run these commands to find your hostname: + +```sh +printf "%s.b32.i2p +" $(head -c 391 /var/lib/i2pd/example.dat | sha256sum | xxd -r -p | base32 | sed s/=//g | tr A-Z a-z) +``` + +*(If you've generated your own keys to obtain a vanity address, now's a good time to make sure i2pd is properly reading those keys by verifying the address is the same as the one generated with the `vain` command.)* + +## Adding the Nginx Config + +From here, the steps are almost identical to setting up a normal website configuration file. Follow the steps as if you were making a new website on the webserver [tutorial](/basic/nginx) up until the server block of code. Instead, paste this: + +```nginx +server { + listen 127.0.0.1:8080 ; + root /var/www/{{<hl>}}example{{</hl>}} ; + index index.html ; +} +``` + +#### Clarifications + +Nginx will listen on port 8080, but i2pd will forward your port 8080 to the i2p site port 80. This way you don't have to deal with server names or anything like that. + +From here we are almost done, all we have to do is enable the site and reload nginx which is also covered in [the webserver tutorial](/basic/nginx#enable). + +### Update regularly! + +Make sure to update I2P on a regular basis by running: + +```sh +apt update && apt upgrade +``` + +**Contributors** +- [qorg11](https://qorg11.net) +- [David Uhden](https://github.com/daviduhden) diff --git a/content/imgcompress.md b/content/imgcompress.md new file mode 100644 index 0000000..49dab19 --- /dev/null +++ b/content/imgcompress.md @@ -0,0 +1,51 @@ +--- +title: "Image compression" +date: 2021-07-17 +--- +Image files will usually have the most impact on the speed of your +websites (aside from Ad/tracker scripts). Learn to slim down your images +using the ubiquitous *ImageMagick* to make your websites faster on slow +internet connections. + +{{< img alt="Image network speed" src="/pix/imgcompress-network.png" link="/pix/imgcompress-network.png" >}} + +For the examples, I decided to use +[this](https://commons.wikimedia.org/wiki/File:Tabby_cat_with_blue_eyes-3336579.jpg) +public domain image. + +{{< img alt="Compressed image of a cat" src="/pix/imgcompress-cat.png" link="/pix/imgcompress-cat.png" >}} + +There are many ways to decrease image size using ImageMagick, the +simplest is to use the `-quality` option, which will compress the image +without changing the resolution. This option takes the value you want to +compress by (between 1 and 100, the lower the value, the lower the file +size). For example: + + convert in.jpg -quality 50 out.jpg + +Compressing the example image above results in the following file size +changes: + +``` + Quality Size + ---------- ------ + Original 2.1M + 90 1.7M + 80 844K + 70 588K + 60 448K + 50 368K + 40 308K + 30 248K + 20 184K + 10 116K +``` + +Due to the images high resolution, it is usable in this website even +when highly compressed (30% quality, still looks decent in my opinion). + +## Contribution + +- [Musse](https://na20a.neocities.org/) +- Monero: + `83is3y69Xv4fkFsTpZhw5c3bfxtimupfgTdpERHM1WtMNAwSqFjTCJm3VabyBKXKnL873dWPmqj4bRcgkm9oCktgQrzmhHd`{.crypto} diff --git a/content/irc.md b/content/irc.md new file mode 100644 index 0000000..d6b601e --- /dev/null +++ b/content/irc.md @@ -0,0 +1,948 @@ +--- +title: "IRC" +date: 2020-07-03 +icon: "irc.svg" +tags: ["service"] +short_desc: "Self-hosting the Internet's classic chat protocol." +--- + +Creating your own chat server for you and your friends is easy, and you +don\'t have to rely on a complicated system to get started. IRC is an +old but gold protocol, and has clients for basically every operating +system made since the 80s, with many powerful modern ones on Linux, Mac, +and Windows. + +Having a chat server for you and your friends makes it impossible for a +group of arbitrarily appointed moderators to deplatform you for +wrong-think, and gives you greater freedom of communication. + +## Installing an IRCd {#installing} + +An IRCd is short for \"IRC daemon\", which just means an IRC server. The +most easy IRCd to set up is [Ergo](https://ergo.chat/). + +The first thing you need to do is create a new user for the server to be +run by. This is good practice for installing software/servers manually, +as it give you more fine-grained control over which permissions the +application has. + +```sh +useradd -m ergo -s /bin/bash +``` + +Next, we want to switch to our newly created `ergo` user and create the +server directory. + +```sh +sudo -i -u ergo +mkdir server +cd server +``` + +You can find the latest release of Ergo on its GitHub [latest +release](https://github.com/ergochat/ergo/releases/latest) page.\ +There are several platforms available, but you want to choose Linux, +most likely `linux-x86_64`.\ +Once you have selected the correct package, copy its URL and replace the +release url with the package URL (still as the `ergo` user): + +```sh +wget "https://github.com/ergochat/ergo/releases/download/v2.15.0/ergo-2.15.0-linux-x86_64.tar.gz" +tar -xf ergo-2.15.0-linux-x86_64.tar.gz +mv ergo-2.15.0-linux-x86_64/* . +rm -r ergo-2.15.0-linux-x86_64* +``` + +Executing `ls -l` should now yield something like this: + +```sh +-rw-r--r-- 1 ergo ergo 118825 Jun 25 00:51 CHANGELOG.md +-rw-r--r-- 1 ergo ergo 1983 Aug 30 01:48 LICENSE +-rw-r--r-- 1 ergo ergo 1983 Oct 11 01:48 README +-rw-r--r-- 1 ergo ergo 41440 Jan 14 00:42 default.yaml +drwxr-xr-x 2 ergo ergo 4096 Feb 2 09:01 docs +-rwxr-xr-x 1 ergo ergo 9654272 Jan 25 00:53 ergo +-rw-r--r-- 1 ergo ergo 1753 Jan 2 01:48 ergo.motd +drwxr-xr-x 2 ergo ergo 12288 Feb 2 09:01 languages +-rw-r--r-- 1 ergo ergo 39722 Jan 14 00:42 traditional.yaml +``` + +If you see something similar to the above, that means Ergo is installed, +although not quite ready to run yet. + +## Configuring Ergo {#configuring} + +Now that Ergo is installed, you want to configure it to fit the needs of +your group.\ +The configuration in this section is tailored towards a small group of +people, and less for a possibly large network, but it should work for +any size of group. + +First thing, make sure you\'re still using the `ergo` user, and are in +the `~/server` directory.\ +If you aren\'t, you can run the following to get back there: + +```sh +sudo -i -u ergo +cd ~/server +``` + +To start configuring, we need to copy some files: + +```sh +cp default.yaml ircd.yaml +cp ergo.motd ircd.motd +``` + +Next, generate certificate files for TLS: + +```sh +./ergo mkcerts +``` + +Ergo comes with a default configuration file with detailed documentation +that can be used to guide you through the configuration process. This +guide will help you setup the server for a typical use-case, but if you +see any settings that you would like to change along the way, go ahead +and change them, as long as you know what you\'re doing. + +The next steps involve editing the newly copied `ircd.yaml` file. If you +do not know how to edit text files from the command line, you can use +`nano`, which is very simple, using arrow keys to navigate, <kbd>CTRL+O</kbd> to +save, and <kbd>CTRL+X</kbd> to exit.\ +Another option is `vim`, which is a much more powerful text editor, but +has a learning curve. It is only recommended for this guide if you +already know how to use it.\ +Lastly, you can copy the `ircd.yaml` file to a text editor on your +computer and edit it with a GUI text editor of your choice. If that is +what you choose to do, you may want to just download the file from +[Ergo\'s +GitHub](https://raw.githubusercontent.com/ergochat/ergo/master/default.yaml), +edit it on your computer, clear the `ircd.yaml` file on the server, and +then paste the contents from your computer into the blank file.\ +No matter how you do it, the next steps assume you can edit the +configuration file. + +**Note**:\ +The options highlighted in this section are not a complete overview of +all options. Instead, the options shown are the ones which are most +relevant to a small network.\ +You should read over the configuration file yourself if you are curious +about everything you can change. + +### Network and server names {#configuring-names} + +One of the first properties in the config file is network name. You can +change this to whatever you like, as it will show up as the name when +you connect to the server. + +```yaml +# network configuration +network: + # name of the network + name: "SiTalk" +``` + +Change the server name to your server\'s domain name. + +```yaml +# server configuration +server: + # server name + name: "{{<hl>}}talk.thesiah.xyz{{</hl>}}" +``` + +### Network password {#configuring-password} + +The next step is optional, depending on if you want your network +password protected or not. The benefit of password protection is fairly +obvious; nobody can connect to your network unless you gave them the +password. If you\'re wanting to run a public network which anyone can +join and create a channel, you want to skip this, but for personal +setups, it is highly recommended. + +Generate a password to use by executing the following: + +```sh +./ergo genpasswd +``` + +It will ask you to enter a password and confirm it, then you will be +given a hashed password.\ +Copy this password, and paste it into the following field (also removing +the `#` before the `password:` line): + +```yaml +# password to login to the server, generated using `ergo genpasswd`: +password: "{{<hl>}}your hashed password{{</hl>}}" +``` + +### Message of the day (MotD) {#configuring-motd} + +Change the MotD (**M**essage **o**f **t**he **D**ay) file to the one you +copied earlier: + +```yaml +# motd filename +# if you change the motd, you should move it to ircd.motd +motd: ircd.motd +``` + +Feel free to edit `ircd.motd` to your heart\'s content. Its contents +will be sent to clients when they connect to the network. + +### IP limits {#configuring-ip-limits} + +For security purposes, you might want to limit the amount of client +connections per IP. For a private network, 4 is likely the maximum +amount of connections you will have per IP, so that is a safe value.\ +If your network is password protected, this is less of an issue, since +the only people connecting will be people who have the password. The +following is the default, but you can change it to be whichever value +you like: + +```yaml +# IP-based DoS protection +ip-limits: + # whether to limit the total number of concurrent connections per IP/CIDR + count: true + # maximum concurrent connections per IP/CIDR + max-concurrent-connections: 16 +``` + +### IP cloaking {#configuring-ip-cloaking} + +Traditionally, IRC networks expose users\' IP addresses to everyone. +This is not a good practice for privacy, however. With Ergo, IP cloaking +is enable by default. You can enable or disable it if you like, and +change how it looks to users.\ +In this case, `netname` was changed to `"chad"`. + +```yaml +# IP cloaking hides users' IP addresses from other users and from channel admins +# (but not from server admins), while still allowing channel admins to ban +# offending IP addresses or networks. In place of hostnames derived from reverse +# DNS, users see fake domain names like pwbs2ui4377257x8.irc. These names are +# generated deterministically from the underlying IP address, but if the underlying +# IP is not already known, it is infeasible to recover it from the cloaked name. +# If you disable this, you should probably enable lookup-hostnames in its place. +ip-cloaking: + # whether to enable IP cloaking + enabled: true + + # whether to use these cloak settings (specifically, `netname` and `num-bits`) + # to produce unique hostnames for always-on clients. you can enable this even if + # you disabled IP cloaking for normal clients above. if this is disabled, + # always-on clients will all have an identical hostname (the server name). + enabled-for-always-on: true + + # fake TLD at the end of the hostname, e.g., pwbs2ui4377257x8.irc + # you may want to use your network name here + netname: "SiTalk" +``` + +### Password enforcement adjustments for HexChat (and possibly other clients) {#configuring-hexchat-password} + +Ergo offers account registration to allow users to do things like use +history and bouncer features, register channels, etc.\ +In clients such as HexChat, server passwords may conflict with account +passwords, so the following setting should be enabled if you wish to use +accounts with clients such as HexChat.\ +Note that this could under some circumstances be considered a security +hazard, as a user with an account does not need to know the server +password to connect, although that user would have needed to register an +account before the server had a password, and then a password would need +to have been set after the fact, so this can be considered a very small +concern if your setup has always had a password.\ +Also keep in mind that this setting has no effect if your network does +not even have a password at all. + +```yaml +# some clients (notably Pidgin and Hexchat) offer only a single password field, +# which makes it impossible to specify a separate server password (for the PASS +# command) and SASL password. if this option is set to true, a client that +# successfully authenticates with SASL will not be required to send +# PASS as well, so it can be configured to authenticate with SASL only. +skip-server-password: true +``` + +### Multiclient, always-on clients, history, etc {#configuring-multiclient} + +Traditionally, IRC servers have no message history, and once you close +your client, you cannot receive messages, and are not shown to be online +at all. Ergo includes functionality to allow users to both receive +history, and keep their clients \"online\" even after they have left. It +also allows multiple clients to connect to the same account.\ +If you are running a private network for friends, you should set +`always-on` and `auto-away` to `opt-out`, to have all users with +accounts to appear as if they are online at all times, and be able to +receive messages when they are offline.\ +For a public network, keep everything as their default values, since you +probably do not want randoms having this by default.\ +If for some reason you do not want any of these features at all, you can +set `enabled` to `false`, but this is not recommended. Below are the +recommended values for a private network (e.g. for friends) where users +with accounts will be able to receive messages and history while they +are offline. + +```yaml +# multiclient controls whether Ergo allows multiple connections to +# attach to the same client/nickname identity; this is part of the +# functionality traditionally provided by a bouncer like ZNC +multiclient: + # when disabled, each connection must use a separate nickname (as is the + # typical behavior of IRC servers). when enabled, a new connection that + # has authenticated with SASL can associate itself with an existing + # client + enabled: true + + # if this is disabled, clients have to opt in to bouncer functionality + # using nickserv or the cap system. if it's enabled, they can opt out + # via nickserv + allowed-by-default: true + + # whether to allow clients that remain on the server even + # when they have no active connections. The possible values are: + # "disabled", "opt-in", "opt-out", or "mandatory". + always-on: "opt-out" + + # whether to mark always-on clients away when they have no active connections: + auto-away: "opt-out" + + # QUIT always-on clients from the server if they go this long without connecting + # (use 0 or omit for no expiration): + #always-on-expiration: 90d +``` + +### VHosts {#configuring-vhosts} + +IP cloaking was mentioned previously, and somewhat related to that, Ergo +includes \"vhost\" functionality, which allows users to set a custom +IP/host string. This is mostly for cosmetic value, and does not +interfere with operators being able to see actual IP addresses for +banning, but if you do not want it enable for some reason, you can +disable it. + +```yaml +# vhosts controls the assignment of vhosts (strings displayed in place of the user's +# hostname/IP) by the HostServ service +vhosts: + # are vhosts enabled at all? + enabled: true +``` + +### Channels {#configuring-channels} + +Channels are where everyone on an IRC network talk. By default, anyone +can create a channel, and anyone with an account can register one. The +difference between a normal channel and a registered one is that the +registered one will preserve the operator status of the person who +created, whereas a normal channel\'s owner will lose operator status if +they leave the channel or disconnect from the network.\ +There are various settings for channels available, but the defaults are +suitable for a private network with trust among users, or where you just +want anyone to have the ability to create a channel. Below are the +default values: + +```yaml +# channel options +channels: + # modes that are set when new channels are created + # +n is no-external-messages and +t is op-only-topic + # see /QUOTE HELP cmodes for more channel modes + default-modes: +nt + + # how many channels can a client be in at once? + max-channels-per-client: 100 + + # if this is true, new channels can only be created by operators with the + # `chanreg` operator capability + operator-only-creation: false + + # channel registration - requires an account + registration: + # can users register new channels? + enabled: true + + # restrict new channel registrations to operators only? + # (operators can then transfer channels to regular users using /CS TRANSFER) + operator-only: false + + # how many channels can each account register? + max-channels-per-account: 15 +``` + +### Operators (administrators, etc) {#configuring-operators} + +The IRC term for an administrator or another privileged user is +\"operator\", or \"oper\" for short.\ +Ergo\'s opers have different permissions that can be granted to them, +and are defined in \"classes\", basically groups of permissions under a +name. For example, \"chat-moderator\" and \"server-admin\" are defined +in the default configuration: + +```yaml +# operator classes +oper-classes: + # chat moderator: can ban/unban users from the server, join channels, + # fix mode issues and sort out vhosts. + "chat-moderator": + # title shown in WHOIS + title: Chat Moderator + + # capability names + capabilities: + - "kill" + - "ban" + - "nofakelag" + - "roleplay" + - "relaymsg" + - "vhosts" + - "sajoin" + - "samode" + - "snomasks" + + # server admin: has full control of the ircd, including nickname and + # channel registrations + "server-admin": + # title shown in WHOIS + title: Server Admin + + # oper class this extends from + extends: "chat-moderator" + + # capability names + capabilities: + - "rehash" + - "accreg" + - "chanreg" + - "history" + - "defcon" + - "massmessage" +``` + +The above can be kept with their default values, but you are free to +modify them or create any new classes that are appropriate for your +setup.\ +Next, let\'s actually create an operator account: + +```yaml +# ircd operators +opers: + # default operator named 'gigachad'; log in with /OPER gigachad <password> + "gigachad": + # which capabilities this oper has access to + class: "server-admin" + + # custom whois line + whois-line: is the server administrator + + # custom hostname + vhost: "SI" + + # normally, operator status is visible to unprivileged users in WHO and WHOIS + # responses. this can be disabled with 'hidden'. ('hidden' also causes the + # 'vhost' line above to be ignored.) + hidden: false + + # modes are modes to auto-set upon opering-up. uncomment this to automatically + # enable snomasks ("server notification masks" that alert you to server events; + # see `/quote help snomasks` while opered-up for more information): + #modes: +is acjknoqtuxv + + # operators can be authenticated either by password (with the /OPER command), + # or by certificate fingerprint, or both. if a password hash is set, then a + # password is required to oper up (e.g., /OPER dan mypassword). to generate + # the hash, use `ergo genpasswd`. + password: "<your oper password>" +``` + +This is a modified version of the default oper entry. The account name +is \"gigachad\", but you can change it to anything.\ +Replace `<your oper password>` with a password generated by +`./ergo genpasswd`, and you will have a new oper account to use.\ +Note that to log into an oper account, clients have to enter +`/OPER <oper name> <oper password>` each time they log in. This can be +automated by most clients by setting the command to be executed when the +client logs in. In the case of HexChat, you can edit your network and +add the command to the `Connect commands` tab of the menu.\ +You can copy everything from `"gigachad"` to the end of the line, paste +it again, and change the name to create another oper account. Another, +less privileged example of an oper is shown as a comment below the above +configuration snippet. + +### Chat history {#configuring-history} + +Traditionally, IRC networks do not store, relay, or handle chat history +in any way.\ +On a privacy standpoint, this is a good thing, since chats are entirely +ephemeral and handled by clients.\ +On a practicality standpoint, this is a bad thing, since people have to +keep a client connected 24/7 to see message history.\ +For normalfriends, this can be a big problem, not only because having to +stay online 24/7 is just annoying or infeasible, but also because they +are likely used to chat platforms that handle history for them.\ +With this in mind, enabling history is a good idea if you want to move +friends over to IRC, and will make things a lot more pleasant for +private networks. + +Ergo\'s `history` configuration group is very long, so it is encouraged +to read over it yourself. This section will go over the most important +pieces of that configuration group. + +History is not endless (unless you want it to be), and the amount that +can be stored for channels is configurable: + +```yaml +# how many channel-specific events (messages, joins, parts) should be tracked per channel? +channel-length: 2048 +``` + +History is already enabled by default, but that just means it is being +collected, not relayed by default. To relay history to clients when they +connect, change the following to the amount of messages that you think +is appropriate: + +```yaml +# number of messages to automatically play back on channel join (0 to disable): +autoreplay-on-join: 250 +``` + +History older than a certain time can be configured to be deleted or be +inaccessible. The default cutoff time is 1 week, but this is +configurable as well. + +```yaml +# options to delete old messages, or prevent them from being retrieved +restrictions: + # if this is set, messages older than this cannot be retrieved by anyone + # (and will eventually be deleted from persistent storage, if that's enabled) + expire-time: 1w +``` + +By default, Ergo only stores chat history in memory, so when the server +restarts, all history is lost. If you wish to have chat history persist +beyond restarts, you must store it in a MySQL database: + +```yaml +# options to store history messages in a persistent database (currently only MySQL). +# in order to enable any of this functionality, you must configure a MySQL server +# in the `datastore.mysql` section. +persistent: + enabled: true + + # store unregistered channel messages in the persistent database? + unregistered-channels: true + +# connection information for MySQL (currently only used for persistent history): +mysql: + enabled: true + host: "localhost" + port: 3306 + # if socket-path is set, it will be used instead of host:port + #socket-path: "/var/run/mysqld/mysqld.sock" + user: "ergo" + password: "hunter2" + history-database: "ergo_history" + timeout: 3s + max-conns: 4 + # this may be necessary to prevent middleware from closing your connections: + #conn-max-lifetime: 180s +``` + +For privacy reasons, you may want to allow users to delete their own +messages in history, or export their messages to JSON: + +```yaml +# options to control how messages are stored and deleted: +retention: + # allow users to delete their own messages from history? + allow-individual-delete: true + + # if persistent history is enabled, create additional index tables, + # allowing deletion of JSON export of an account's messages. this + # may be needed for compliance with data privacy regulations. + enable-account-indexing: true +``` + +### Spam reduction {#configuring-spam} + +Most IRC networks have measures in place to reduce chat spam. By +default, \"fakelag\" is enabled in Ergo, and that can deal with most +aggregious chat spam.\ +If you are running a private network where user trust is high, you can +disable it so that there are no limits on the speed that messages can be +sent. + +```yaml +# fakelag: prevents clients from spamming commands too rapidly +fakelag: + # whether to enforce fakelag + enabled: true + + # time unit for counting command rates + window: 1s + + # clients can send this many commands without fakelag being imposed + burst-limit: 5 + + # once clients have exceeded their burst allowance, they can send only + # this many commands per `window`: + messages-per-window: 2 + + # client status resets to the default state if they go this long without + # sending any commands: + cooldown: 2s +``` + +## Starting and using your server + +Now that Ergo is both installed and configured, you can actually start +using it! + +### Starting the server {#using-starting} + +First thing, make sure you\'re still using the `ergo` user, and are in +the `~/server` directory.\ +If you aren\'t, you can run the following to get back there: + +```sh +sudo -i -u ergo +cd server +``` + +Starting the server is done in one command: + +```sh +./ergo run +``` + +It will stay online until you close the terminal, or press <kbd>CTRL+C</kbd>. +Don\'t worry, the next section goes over how to make it run like a +normal server with a SystemD service.\ +If you have not already, make sure the port `6697` is not blocked on +your server. If you are using UFW as your firewall, you need to run +`ufw enable 6697` (not as the `ergo` user, of course).\ +If you make and configuration changes while the server is running, you +can apply them without restarting by typing `/rehash` as an operator. + +### Connecting to the server {#using-connecting} + +To use IRC, you of course need an IRC client. There are many choices +available, but the most widely used for Windows and Linux is +[HexChat](https://hexchat.github.io/). On Mac, you have a slightly nicer +option with [Textual](https://www.codeux.com/textual/), although you +have to [compile it from +source](https://github.com/Codeux-Software/Textual/#building-textual) if +you want to use it for free.\ +A more user-friendly and modern client choice is TheLounge, which is +explained in the last section of this guide, if you want to look into +it. + +Connecting with HexChat is very easy. When you start it, you will see +something like this: + +{{< img alt="HexChat network select" src="/pix/irc/hexchat-network-select.png" link="/pix/irc/hexchat-network-select.png" >}} + +From there, you should click `+ Add` and name the server whatever you +like (so you can find it on the server list).\ +Once you have created a new server and named it, select it and click +`Edit...`. A menu will show up like the one below. Change the domain to +whatever domain your server is running on, and make sure to put in your +server password if you set one. + +{{< img alt="HexChat network edit menu" src="/pix/irc/hexchat-network-edit.png" link="/pix/irc/hexchat-network-edit.png" >}} + +Once you\'re done editing the network, click `(X) Close`, select your +network from the network list, and click `Connect`.\ +If all is well, you should be connected! + +{{< img alt="HexChat connection complete" src="/pix/irc/hexchat-connection-complete.png" link="/pix/irc/hexchat-connection-complete.png" >}} + +The process is very similar on Textual.\ +Create a new network and connect to it. Note that it will ask if you +want to connect even though the certificate is unsigned. This is due to +the self-signed certificates generated for the server, and is not a +problem or security vulnerability, it is just a little annoying. + +{{< img alt="Textual network edit menu" src="/pix/irc/textual-network-edit.png" link="/pix/irc/textual-network-edit.png" >}} + +Surviving restarts with a SystemD service + +In the beginning of the last section, Ergo was started by simply running +`./ergo run`, but this is only suitable for testing. To have a proper +server setup, you need to run it as a service. This can be achieved via +a SystemD service. + +Before creating your service file, make sure you are in `~/server` as +the `ergo` user.\ +Once you have done that, create a file called `start.sh` with the +following content: + +```sh +#!/bin/bash +./ergo run +``` + +Save the file, then mark it as executable: + +```sh +chmod +x start.sh +``` + +Now, create a file called `ergo.service` with the following content: + +```systemd +[Unit] +Description=Ergo IRC server +After=network.target +# If you are using MySQL for history storage, comment out the above line +# and uncomment these two instead (you must independently install and configure +# MySQL for your system): +# Wants=mysql.service +# After=network.target mysql.service + +[Service] +Type=simple +User=ergo +WorkingDirectory=/home/ergo/server +ExecStart=/home/ergo/server/start.sh +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +LimitNOFILE=1048576 +# Uncomment this for a hidden service: +# PrivateNetwork=true + +[Install] +WantedBy=multi-user.target +``` + +You now have your service file, but it is not installed yet. To install +it, switch to your normal user, and execute the following lines to +install, enable, and start the SystemD service: + +```sh +ln -s /home/ergo/server/ergo.service /etc/systemd/system/ergo.service +systemctl enable ergo +systemctl start ergo +``` + +Ergo is now installed and running as a service, and will automatically +start when the system boots. + +## Registering accounts and channels {#registering} + +Account and channel registration were mentioned multiple times in this +guide, and are indeed very important parts of the modern IRC ecosystem. +You can connect to most IRC networks and talk without creating an +account, but you will not be able to reserve your nickname or register +channels, so it is important to register an account. + +### Registering an account with NickServ {#registering-accounts} + +First, make sure you are connected to your IRC network. Once you are, +type `/nickserv help` to make sure NickServ (the registration system) is +working propertly.\ +If all is well, type the following, replacing `<your password>` with the +password you want to use: + +```txt +/nickserv register <your password> +``` + +At this point, you are now registered!\ +The final step is to configure authentication with your client. + +In HexChat, all that needs to be done is changing `Login method` to +`SASL (username + password)`, and entering your NickServ password that +you used earlier into the password field: + +{{< img alt="HexChat SASL in network edit menu" src="/pix/irc/hexchat-sasl.png" link="/pix/irc/hexchat-sasl.png" >}} + +In Textual, open up your network in the menu, and click `Identity` under +`Server Properties`. Enter your password in `Personal Password`, and +check `Wait for identification before joining channels`. + +{{< img alt="Textual identity menu" src="/pix/irc/textual-identity.png" link="/pix/irc/textual-identity.png" >}} + +You will now be logged into your account when you connect to your +network. + +### Registering channels with ChanServ {#registering-channels} + +Once you have an account registered, you can register channels with +ChanServ.\ +To do so, join the channel you want to register, then type the +following, replacing `<your channel>` with the name of the channel you +want to register: + +```txt +/chanserv register #<your channel> +``` + +You are now the channel owner, and are free to appoint operators, +administrators, etc for it. When you go offline, you won\'t lose +ownership, and you cannot be removed as the owner unless you unregister +the channel later. + +## Moderation + +Like any chat, there will come a point where you need to use moderation +tools to keep things under control. Many IRC setup guides do not go over +moderation, so it can be stressful when operators need to actually use +moderation tools.\ +The main difference between IRC and other chat systems in terms of +moderation is the difference between channel bans and network bans. +Channel ban keeps a person out of channel a channel, whereas a network +ban keeps a person out of the entire network. + +### Understanding masks {#moderation-masks} + +Bans are applied \"masks\", which are formatted pieces of text that +contain a user\'s nick (username), their realname value, and their IP +address or host.\ +This is what a mask looks like: `nick!~nick-dude@127.0.0.1`.\ +In bans, asterisks can be used as wildcards, which is useful for banning +IP address ranges, patterns of nicknames, or whatever else you can think +of.\ +A ban on the nick `person`, for example, would look like this: +`person!*@*`.\ +A ban on anyone with the IP address `127.0.0.1` would look like this: +`*!*@127.0.0.1` + +### Discovering real IPs {#moderation-real-ips} + +Even if IP cloaking is enabled on your network, you can still obtain +real IP addresses/hosts if you are an operator. See the **Operators** +part of the configuration section of this guide on how to become an +operator.\ +To find out a user\'s real IP, simply type `/whois` along with the +user\'s nick, and you will see information about the user, along with +their real IP address/host.\ +`/whois` is not a command that is exclusive to operators, but it does +not reveal as much information to non-operators. + +### Banning someone from the network {#moderation-network-ban} + +Any netword-wide moderation action requires being an operator. See the +**Operators** part of the configuration section of this guide on how to +become an operator.\ +Banning someone from the network is achieved with the `/kline` command. +To see more info on the command, type `/helpop kline`.\ + +To ban a nick from the network: + +```txt +/kline andkill <nick>!*@* +``` + +To ban an IP address or host from the network: + +```txt +/kline andkill *!*@<IP or mask> +``` + +To unban a mask, you can use the `/unkline` command with the mask you +want to unban. + +### Banning someone from a channel {#moderation-channel-ban} + +Channel owners, administrators, and operators can ban people from +channels. This is not the same as banning someone from the network, +since it only has an effect on one channel. Additionally, a channel +operator is not the same as a network operator. + +To ban someone in a channel, type the following in that channel, +replacing `<mask>` with the user\'s mask: + +```txt +/mode +b <mask> +``` + +Note that this will only ban the user, not kick them immediately. You +will want to run `/kick` along with the user\'s nick to also kick them.\ +To unban a user, run the command above, but replace the `+` with a `-`.\ +You can see who is banned in a channel by typing `/banlist`. + +### Muting people in a channel {#moderation-muting} + +By default, anyone can speak in an IRC channel. To change this, you must +be a channel owner, administrator, or operator.\ +Channels, along with users, have modes, which modify their behavior. +There is a special mode for channels called `m` (moderated) which +requires users to be privileged in some way to talk.\ +To set a channel as moderated, type the following in the channel: + +```txt +/mode +m +``` + +Now, users must be an owner, administrator, operator, or be voiced to +talk in the channel This be reversed by typing the command above, but +changing the `+` to a `-`.\ +To voice a user, run the following, replacing _\<nick\>_ with the +user\'s nick: + +```txt +/mode +v <nick> +``` + +Unvoice the user by typing the above command, but replacing the `+` with +a `-`. + +### Appointing channel administrators and operators {#moderation-appointing} + +Assuming you a channel owner, you can appoint both administrators and +operators. If you are only an operator, you may only appoint operators.\ +The difference between administrator and operator is mainly that +administrators cannot have their privileges taken away by operators, +only owners. To appoint an administrator, type the following, replacing +_\<nick\>_ with the user\'s nick: + +```txt +/mode +a <nick> +``` + +To appoint an operator, type the following, replacing _\<nick\>_ with +the user\'s nick: + +```txt +/mode +o <nick> +``` + +You can also use `/op` and `/deop` on most clients to appoint and remove +an operator.\ +To remove administrator or operator status, run either of the above +commands, but replace the `+` with a `-`. + +Bringing modern-day features to IRC with TheLounge + +A large downside to IRC as a protocol is just how old it is, and the +limitations that exist because of it. Other old protocols such as HTTP +were built to be content-agnostic and versitile, but IRC was built with +a very specific set of features, so it has not held up so well to +contemporary chat systems.\ +A notable thing that IRC as a protocol is missing is file uploads, and +other fancy features that many other chats have.\ +With that said, these problems can be fixed by clients, although many +clients are still very primitive. + +[TheLounge](https://thelounge.chat/) is a modern self-hosted IRC web +client that tries to make IRC as user-friendly as possible. It can be +the answer to many of the complaints that normalfriends may have about +IRC. It runs on anything with a web browser, can be \"installed\" since +it is a PWA (Progressive Web App), and is optimized for both desktops +and mobile devices. It keeps you logged in even when you are gone, and +even supports file uploads and embeds.\ +Effectively, it brings IRC up to the standard of most other chat +systems. + +If you would like to setup an instance of TheLounge for you and your +friends, you can take a look at their [installation +guide](https://thelounge.chat/docs/install-and-upgrade).\ +It is a self-hosted web app, so you can run it for multiple people, not +just yourself. + +--- + +_Written by [Termer](https://termer.net/)_ diff --git a/content/jitsi.md b/content/jitsi.md new file mode 100644 index 0000000..0df893b --- /dev/null +++ b/content/jitsi.md @@ -0,0 +1,199 @@ +--- +title: "Jitsi" +date: 2021-07-31 +icon: "jitsi.svg" +tags: ['service'] +short_desc: "Video-chat software." +--- + +<dfn>Jitsi</dfn> is a set of open-source projects that allows you to easily +build and deploy secure video conferencing solutions. + +Is really easy to install, and also a really good private, federated and +libre alternative to Zoom or other video conferencing software. You can +create calls just by typing the URL, and loging-in is not necessary. + +## Dependencies and Installation + +First, install some dependencies: + +```sh +apt install gpg apt-transport-https nginx python3-certbot-nginx +``` + +Jitsi has its own package repository, so let\'s add it. + +```bash +curl https://download.jitsi.org/jitsi-key.gpg.key | gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg +echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' > /etc/apt/sources.list.d/jitsi-stable.list +apt update -y +``` + +Ok. So now we can install Jitsi, but before we do that, let\'s setup the +firewall `ufw`, in case you have it enabled, and the SSL certificate. + +## Enable Required Ports + +If you are using [ufw](/ufw) or another firewall, there are several +ports we need to ensure are open: + +```sh +ufw allow 80/tcp +ufw allow 443/tcp +ufw allow 10000/udp +ufw allow 3478/udp +ufw allow 5349/tcp +ufw enable +``` + +For your information, these allow the following: + +- 80 TCP -- Certbot. +- 443 TCP -- General access to Jitsi Meet. +- 10000 UDP -- General network video/audio communications. +- 3478 UDP -- Quering the stun server ([Coturn](/coturn), optional, needs config.js change to enable it). +- 5349 TCP -- Fallback network video/audio communications over TCP (when UDP is blocked for example), served by [Coturn](/coturn). + +## SSL certificate + +I\'ll be using [certbot](/basic/certbot) and +[Nginx](/basic/nginx) to generate a certificate for the +Jitsi subdomain to allow encrypted connections. + +```sh +certbot --nginx certonly -d {{<hl>}}meet.example.org{{</hl>}} +``` + +We will not create an Nginx config file for Jitsi because the Jitsi +package we will be installing will do that automatically. + +## Installation + +To begin the installation process, just run: + +```sh +apt install jitsi-meet +``` + +It will ask you for your `hostname`; there you\'ll need to input the +subdomain you have just added to Nginx, like `{{<hl>}}meet.example.org{{</hl>}}`. + +For the SSL certificate, choose `I want to use my own certificate`. + +When it ask you for the certification key and cert files, input +`/etc/letsencrypt/live/{{<hl>}}meet.example.org{{</hl>}}/privkey.pem` and +`/etc/letsencrypt/live/{{<hl>}}meet.example.org{{</hl>}}/fullchain.pem` respectively. + +## Using Jitsi + +{{< img alt="Jitsi once installed" src="/pix/jitsi-01.webp" >}} + +Jitsi can be used in a browser by then just going to `{{<hl>}}meet.example.org{{</hl>}}`. + +Note that there are also Jitsi clients for all major platforms: + +- [Desktop](https://desktop.jitsi.org/Main/Download.html) (Windows, + MacOS, GNU/Linux) +- Android ([F-Droid](https://f-droid.org/en/packages/org.jitsi.meet/) + and [Google + Play](https://play.google.com/store/apps/details?id=org.jitsi.meet)) +- [iPhone/iOS](https://apps.apple.com/us/app/jitsi-meet/id1165103905) + +**When using a Jitsi app for the first time, remember to go to the +\"Settings\" menu and change your server name to the Jitsi site you just +created.** + +When you create a video chatroom, its address will appear as +`meet.example.org/yourvideochatname` and can be shared as such. + +## Security + +By default, anyone who has access to **meet.example.org** will be able +to create a chatroom. You probably don\'t want that, so you\'ll need to +set up some authentication. The simplest option is to handle +authentication through the local [Prosody](/prosody) user +database. + +### Prosody configuration + +First, we need to enable password authentication in +[Prosody](/prosody). Edit +`/etc/prosody/conf.avail/{{<hl>}}meet.example.org{{</hl>}}.cfg.lua`, and locate this +block: + +```lua +VirtualHost "{{<hl>}}meet.example.org{{</hl>}}" + authentication = "anonymous" +``` + +And change the authentication mode from `"anonymous"` to +`"internal_hashed"`. + +Then, to enable guests to login and join your chatrooms, add the +following block **after** the one you just edited: + +```lua +VirtualHost "guest.{{<hl>}}meet.example.org{{</hl>}}" + authentication = "anonymous" + c2s_require_encryption = false +``` + +### Jitsi Meet configuration + +Next, in `/etc/jitsi/meet/{{<hl>}}meet.example.org{{</hl>}}-config.js`, uncomment the +following line: + +```js +var config = { + hosts: { + // anonymousdomain: 'guest.jitsi-meet.example.com', + }, +} +``` + +And change `'guest.jitsi-meet.example.com'` to +`'{{<hl>}}guest.meet.example.org{{</hl>}}'` (your Jitsi domain preceded by `meet.`). + +### Jicofo configuration + +Finally, we configure Jicofo to only allow the creation of conferences +when the request is coming from an authenticated user. To do so, add the +following `authentication` section to `/etc/jitsi/jicofo/jicofo.conf`: + +```yaml +jicofo { + authentication: { + enabled: true + type: XMPP + login-url: {{<hl>}}meet.example.org{{</hl>}} + } +``` + +### Create users in Prosody and restart the services + +You now need to register some users in [Prosody](/prosody), you +can do so manually using `prosodyctl`: + +```sh +prosodyctl register <username> meet.example.org <password> +``` + +Finally, restart `prosody`, `jicofo`, and `jitsi-videobridge2`: + +```sh +systemctl restart prosody +systemctl restart jicofo +systemctl restart jitsi-videobridge2 +``` + +## More info + +This article is based on [the original +documentation](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart). +There you can find more details and configurations. + +- Written by [Jose Fabio.](https://josefabio.com) + Donate Monero: + `484RLdsXQCDGSthNatGApRPTyqcCbM3PkM97axXezEuPZppimXmwWegiF3Et4BHBgjWR7sVXuEUoAeVNpBiVznhoDLqLV7j` + [\[QR\]](https://josefabio.com/figures/monero.jpg) +- Edited and revised by [Luke](https://lukesmith.xyz). diff --git a/content/mail/inbox.md b/content/mail/inbox.md new file mode 100644 index 0000000..3f70b9c --- /dev/null +++ b/content/mail/inbox.md @@ -0,0 +1,214 @@ +--- +title: "Setting up an E-mail Inbox" +tags: ['mail'] +date: 2022-12-04 +--- +In the article on [SMTP and Postfix](/mail/smtp), we set up a simple +Postfix server that we could use to programatically send mail with the +`mail` command. In order to have a true and fully-functional mail +server, users should be able to login to a mail client where they +can read their inbox and send mail remotely. In order to achieve this we need Dovecot, +which can store mails received by the server, +authenticate user accounts and interact with mail. + +If we're setting up an inbox we will also want spam detection software, such +as spam assassin. + +## Dovecot and Spamassassin + + apt install dovecot-imapd dovecot-sieve spamassassin spamc + +Unblock the imap port: + + ufw allow 993 + +## Certificate + +We will want a SSL certificate for the `mail.` subdomain. We can get +this with [Certbot](/basic/certbot/). Assuming we are using Nginx for our +server otherwise, run: + + certbot --nginx certonly -d mail.example.org + +## DNS + +We also need two little DNS records set on your domain registrar's site/DNS server: + +1. An MX record. Just put your domain, **example.org**, in the "Points to" field. +2. A CNAME record. Host field: **mail.example.org**. "Points to" field: **example.org.** + +## Configuring Dovecot + +Dovecot\'s configuration file is in `/etc/dovecot/dovecot.conf`. If you +open that file, you will see this line: `!include conf.d/*.conf` which adds +all the `.conf` files in `/etc/dovecot/conf.d/` to the Dovecot +configuration. + +One can edit each of these files individually to get the needed +configuration, but to make things easy here, delete or backup the main +configuration file and we will replace it with one single config file +with all important settings in it. Make sure you change `ssl_cert` +and `ssl_key` accordingly. + +``` wide +# Note that in the dovecot conf, you can use: +# %u for username +# %n for the name in name@domain.tld +# %d for the domain +# %h the user's home directory + +# Connections between the mail client and Dovecot needs to be encrypted +ssl = required +ssl_cert = </etc/letsencrypt/live/mail.example.org/fullchain.pem +ssl_key = </etc/letsencrypt/live/mail.example.org/privkey.pem +ssl_min_protocol = TLSv1.2 +ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED +ssl_prefer_server_ciphers = yes +ssl_dh = </usr/share/dovecot/dh.pem +auth_mechanisms = plain login +auth_username_format = %n + +protocols = $protocols imap + +# Search for valid users in /etc/passwd +userdb { + driver = passwd +} +#Fallback: Use plain old PAM to find user passwords +passdb { + driver = pam +} + +# Our mail for each user will be in ~/Mail, and the inbox will be ~/Mail/Inbox +mail_location = maildir:~/Mail:INBOX=~/Mail/Inbox:LAYOUT=fs +namespace inbox { + inbox = yes + mailbox Drafts { + special_use = \Drafts + auto = subscribe +} + mailbox Junk { + special_use = \Junk + auto = subscribe + autoexpunge = 30d +} + mailbox Sent { + special_use = \Sent + auto = subscribe +} + mailbox Trash { + special_use = \Trash +} + mailbox Archive { + special_use = \Archive +} +} + +# Here we let Postfix use Dovecot's authetication system. +service auth { + unix_listener /var/spool/postfix/private/auth { + mode = 0660 + user = postfix + group = postfix +} +} + +protocol lda { + mail_plugins = $mail_plugins sieve +} +protocol lmtp { + mail_plugins = $mail_plugins sieve +} +plugin { + sieve = ~/.dovecot.sieve + sieve_default = /var/lib/dovecot/sieve/default.sieve + sieve_dir = ~/.sieve + sieve_global_dir = /var/lib/dovecot/sieve/ +} +``` + +### Settings Explained + +Take a good look at the above settings to understand what\'s going on. Some of +the settings include: + +1. SSL settings to allow encrypted connections. +2. The mail server will authenticate users against PAM/passwd, which + means users you create on the server (so long as they are part of + the `mail` group) will be able to receive and send mail. +3. Default directories for a mail account: Inbox, Sent, Drafts, Junk, + Trash and Archive. +4. Create a `unix_listener` that will allow Postfix to authenticate + users via Dovecot. +5. Setup the Dovecot sieve plugin, which provides mail filtering facilities + at time of final message delivery. Sieve scripts can be used to + customize how messages are delivered, whether they're forwarded + or stored in special folders. + +Next, we can tell sieve to automatically move mail flagged as spam to +the junk folder: + + echo "require [\"fileinto\", \"mailbox\"]; + if header :contains \"X-Spam-Flag\" \"YES\" + { + fileinto \"Junk\"; + }" > /var/lib/dovecot/sieve/default.sieve + +After that, we should create the `vmail` user and group, which will +access the mails, and then update the sieve configuration: + + grep -q '^vmail:' /etc/passwd || useradd vmail + chown -R vmail:vmail /var/lib/dovecot + sievec /var/lib/dovecot/sieve/default.sieve + +Then, enable pam authentication for Dovecot: + + echo "auth required pam_unix.so nullok + account required pam_unix.so" >> /etc/pam.d/dovecot + +## Connecting Postfix and Dovecot + +We need to tell Postfix to look to Dovecot for authenticating users/passwords. +Dovecot will be putting an authentication socket in `/var/spool/postfix/private/auth`. + + postconf -e 'smtpd_sasl_auth_enable = yes' + postconf -e 'smtpd_sasl_type = dovecot' + postconf -e 'smtpd_sasl_path = private/auth' + postconf -e 'mailbox_command = /usr/lib/dovecot/deliver' + +## Connecting Postfix and Spamassassin + +We will change `/etc/postifx/master.cf` so postfix can route mail through spamassassin. First +we can cleanup the default configuration. Feel free to make a backup. + + sed -i '/^\s*-o/d;/^\s*submission/d;/^\s*smtp/d' /etc/postfix/master.cf + +Finally, run this command to finish the configuration for spamassassin. + + echo "smtp unix - - n - - smtp + smtp inet n - y - - smtpd + -o content_filter=spamassassin + submission inet n - y - - smtpd + -o syslog_name=postfix/submission + -o smtpd_tls_security_level=encrypt + -o smtpd_sasl_auth_enable=yes + -o smtpd_tls_auth_only=yes + smtps inet n - y - - smtpd + -o syslog_name=postfix/smtps + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes + spamassassin unix - n n - - pipe + user=debian-spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}" >> /etc/postfix/master.cf + +## Make new mail accounts + +This is the easy part. Let's say we want to add a user Billy and let him +receive mail, run this: + + useradd -m -G mail billy + passwd billy + +Any user added to the `mail` group will be able to receive mail. Suppose a user +Cassie already exists and we want to let her receive mail too. Just run: + + usermod -a -G mail cassie diff --git a/content/mail/rdns.md b/content/mail/rdns.md new file mode 100644 index 0000000..85cce0f --- /dev/null +++ b/content/mail/rdns.md @@ -0,0 +1,36 @@ +--- +title: "Setup rDNS" +tags: ['mail'] +date: 2022-12-02 +--- + +While [DNS records](/basic/dns) refer a domain name to the IP address +where the the website is hosted, there is also rDNS (reverse DNS) and +specifically PTR (pointer) records which do the reverse: link a +server\'s IP to a domain name. + +This is important for many things, but especially email. Many email +servers require that other servers that send them mail have PTR records +to prevent spam. + +## Setting your PTR Record + +DNS settings are set with your registrar, while rDNS settings are set +with your server or VPS provider. **Remember to set records for both +IPv4 and IPv6!** + +In [Vultr](https://www.vultr.com/?ref=8384069-6G) we want to set the +IPv4 record, click on the server, then \"Settings,\" and make sure the +\"IPv4\" tab is selected. We can then edit the \"Reverse DNS\" blank +shown below. + +{{< img alt="IPv4 rDNS PTR record set in Vultr" src="/pix/rdns-01.png" >}} + +The setting for IPv6 is obviosuly under the IPv6 tab. Note here that we +copy the full IPv6 address from above and create a new rDNS entry by +pasting that and the domain name in the blanks below. Then just select +\"Add.\" + +{{< img alt="IPv6 rDNS PTR record set in Vultr" src="/pix/rdns-02.png" >}} + +That\'s it! diff --git a/content/mail/security.md b/content/mail/security.md new file mode 100644 index 0000000..4527b34 --- /dev/null +++ b/content/mail/security.md @@ -0,0 +1,72 @@ +--- +title: "Harden your E-mail Server" +tags: ["mail"] +date: 2022-12-05 +--- + +## Hardening Postfix + +Put restrictions on servers sending mail to you. + + postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unknown_recipient_domain' + +## Anonymize Headers + +Use some regular expressions to prevent some meta data like a client's ip address +from being leaked. + + echo "/^Received:.*/ IGNORE + /^X-Originating-IP:/ IGNORE + /^User-Agent:/ IGNORE + /^X-Mailer:/ IGNORE" >> /etc/postfix/header_checks + +Add this file to the postfix configuration: + + postconf -e "header_checks = regexp:/etc/postfix/header_checks" + +## Fail2Ban + +If you're not familiar with fail2Ban, it's essentially a program which +blocks bot's and hacker's login requests after a few invalid attempts. + + apt-get install fail2ban + +Make a local copy of the configuration file: + + cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local + +Go down to the `# Mail servers` line and paste this: + + [postfix] + + enabled = true + port = smtp,ssmtp,submission + filter = postfix + logpath = %(postfix_log)s + backend = systemd + + + [sasl] + + enabled = true + port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s + filter = postfix[mode=auth] + # You might consider monitoring /var/log/mail.warn instead if you are + # running postfix since it would provide the same log lines at the + # "warn" level but overall at the smaller filesize. + logpath = %(postfix_log)sAdd commentMore actions + backend = systemd + maxretry = 1 + bantime = 21600 + + [dovecot] + + enabled = true + port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s + filter = dovecot + logpath = %(dovecot_log)sAdd commentMore actions + backend = systemd + +This will only grant 2 login attempts and then block the requester for 6 hours. Now restart `fail2ban`: + + systemctl restart fail2ban diff --git a/content/mail/smtp.md b/content/mail/smtp.md new file mode 100644 index 0000000..d5c1f48 --- /dev/null +++ b/content/mail/smtp.md @@ -0,0 +1,74 @@ +--- +title: "Sending and Receiving Email" +tags: ["mail"] +date: 2022-12-01 +--- + +The first step to setting up an email server is having an SMTP server. +SMTP sends and receives email. Whether we want a full email server or +just the ability to send automated email by script, we will need SMTP, +and Postfix is the standard SMTP server. + +Here let\'s set a server up. Note that our goal is to be able to send +emails from our server. If you want a full email server, this is the +first step, and we will address the rest later. + +## Before beginning! + +Whatever VPS ([Vultr](https://www.vultr.com/?ref=8384069-6G) or +[Frantech](https://my.frantech.ca/aff.php?aff=3886)) or IPS you are +using, it is a very common policy to **automatically block all email +ports by default**. VPS providers do this to prevent spammers from using +their services. + +If you want to start an email server, therefore, go to your VPS\'s site +and open a ticket or make a request to open up email ports, notably port `25`. This is a +simple process that requires nothing too special. One of the wagies at +your VPS will kindly do the needful and open your ports for you. Note +that this is not the same as unblocking a port with [ufw](/../ufw), +which still needs to be done for SMTP to work. + + ufw allow 25,587 proto tcp + +## Installation + +First, we install Postfix and also `mailutils`, which comes with some +mail programs we will use. + + apt install -y mailutils postfix + +Installing Postfix for the first time will give us some graphical +options. + +{{< img alt="SMTP Postfix internet site choice" src="/pix/smtp-01.png" link="/pix/smtp-01.png" >}} + +When asked for a \"mail name\", give your full domain name from which +you would like mail to come and go, e.g. **example.org** or +**chad.thesiah.xyz** + +{{< img alt="SMTP Postfix fully qualified domain name" src="/pix/smtp-02.png" link="/pix/smtp-02.png" >}} + +## Test the email + +That is actually all you need to have set up to have a barebones, +send-only email server. We can test our server by running a `mail` +command like that below. + + echo "Hi there. + + This is the text." | mail -s "Email from the server" your@emailaddress.com + +This type of command is sufficient enough for your server to send mail. +Note that we use the `-s` option to specify the email\'s subject while +we pipe the email content into the `mail` command via standard input. In +this example I use a quoted multiline email as an example. + +## Do you see your message? + +If you sent the above test message to an account on Gmail or another +major email provider, there is **very high** chance of the message you +sent above being marked as spam or not appearing at all! + +Don\'t worry, we\'ll take care of that in the next two articles where we +set up rDNS with your VPS provider and various other DNS +records to validate the emails you send. diff --git a/content/mail/validate.md b/content/mail/validate.md new file mode 100644 index 0000000..8447409 --- /dev/null +++ b/content/mail/validate.md @@ -0,0 +1,230 @@ +--- +title: "Validate Email with DNS Records" +tags: ['mail'] +date: 2022-12-03 +--- +Email is a lot like real-life mail. You can send email to anyone, but +you can also write whatever return address you\'d like. That is, it\'s +pretty easy to pretend to be someone else via mail, and that was +originally the case with email as well: email is just text, and you +could just change your `From:` address to any email address you wanted! +DKIM (Domain Keys Identified Mail) helps solve this issue. + +OpenDKIM will generate a public/private cryptographic key pair for your +server. The public key will be made available publicly in your server\'s +DNS records and the private key will be used to sign every single email +that leaves the server. This means that people receiving mail from your +server can now be absolutely sure that it originated from your server +because their servers can check the cryptographic signature on the email +with the public key! + +OpenDKIM ensures that email originated from the server it claims it did, +but it does not ensure that it originated from the user account it +claims it did. This easier problem is solved by server-side +authorization settings. + +## Installation + +```sh +apt install opendkim opendkim-tools +``` + +## The Keys and Files + +We have to generate the DKIM keys and create some secondary files that +will be required for our configuration. + +### Generate the DKIM key + +<!-- +TODO: Make a unique directory for each domain to later allow multiple domain +DKIM validation for servers serving more than one domain name. +--> + +Here we create directories for the OpenDKIM keys, generate them, and +ensure they have the right file permissions. + +```sh +mkdir -p /etc/postfix/dkim +opendkim-genkey -D /etc/postfix/dkim/ -d example.org -s mail +chgrp opendkim /etc/postfix/dkim/* +chmod g+r /etc/postfix/dkim/* +``` + +### Create the key table + +Now we\'ll tell OpenDKIM where the newly generated keys are on the file +system. + +```sh +echo "mail._domainkey.example.org example.org:mail:/etc/postfix/dkim/mail.private" > /etc/postfix/dkim/keytable +``` + +### Create the signing table + +```sh +echo "*@example.org mail._domainkey.example.org" > /etc/postfix/dkim/signingtable +``` + +### Adding trusted hosts + +```sh +echo "127.0.0.1 +10.1.0.0/16 +1.2.3.4/24" > /etc/postfix/dkim/trustedhosts +``` + +## Configuring opendkim.conf + +Now we have all the raw material, so open up `/etc/opendkim.conf` and we +can finalize our server settings. First, add these lines that will +source the files we just created. + +```yaml +KeyTable file:/etc/postfix/dkim/keytable +SigningTable refile:/etc/postfix/dkim/signingtable +InternalHosts refile:/etc/postfix/dkim/trustedhosts + +Canonicalization relaxed/simple +Socket inet:12301@localhost +``` + +There will already be an uncommented `Socket` directive, so delete, +comment out or replace it with the above. + +## Interfacing with Postfix + +There are a couple things we must add to the Postfix SMTP server +settings to interface it with OpenDKIM. Specifically, we have to set our +OpenDKIM server, which will be running on port `12301`, as a milter +(mail filter). This is easy to do with the four commands below: + +```sh +postconf -e "myhostname = $(cat /etc/mailname)" +postconf -e "milter_default_action = accept" +postconf -e "milter_protocol = 6" +postconf -e "smtpd_milters = inet:localhost:12301" +postconf -e "non_smtpd_milters = inet:localhost:12301" +``` + +## Restart and reload Postfix and DKIM + +Now that we have all our settings in place: + +```sh +systemctl restart opendkim +systemctl enable opendkim +systemctl reload postfix +``` + +## Adding the DNS record! + +We are only one step away from having functioning OpenDKIM. We must add the +DKIM public key to our server\'s DNS settings, so go ahead and open up your +registrar\'s site or wherever your site\'s DNS settings are. + +The public key is found in the file `/etc/postfix/dkim/mail.txt`, but it +will display as multiple lines and multiple quoted strings, which is +annoying and hard to copy-and-paste into your registrar. To make things +easier, run the following command to format the key in the way we need +it for the DNS TXT entry: + +```sh +echo -e " + +v=DKIM1; k=rsa; $(tr -d " +" </etc/postfix/dkim/mail.txt | sed "s/k=rsa.* \"p=/k=rsa; p=/;s/\"\s*\"//;s/\"\s*).*//" | grep -o "p=.*") + +" +``` + +Take the very long output of that command, which will start with +`v=DKIM1` and add it as a TXT entry in your DNS settings as below. The +host we put it for is `mail._domainkey`. + +{{< img alt="Adding the OpenDKIM TXT entry in DNS settings" src="/pix/dkim-01.png" link="/pix/dkim-01.png" >}} + +On my registrar, this is how it is input, but on some registrars, it may be +required to include your domain name as well as `mail._domainkey.example.org`. + +If you have your own DNS server, add a TXT entry as follows: + +```txt +mail._domainkey.example.org TXT v=DKIM1; k=rsa; p=ThatLongRandomSequenceOfLettersAndNumbersOfYours +``` + +## Testing it out! + +Now we want to send an email to make sure that your emails will now be +signed with OpenDKIM. + +### Hostname + +If you\'ve followed these instructions, all emails from the domain +**example.org** will now have a DKIM signature on them. If we send mail +via the `mail` command, however, their domain of origin will be whatever +your server\'s hostname is, which you may have set to something +different than your domain. + +You can permanently change your hostname by changing it in +`/etc/hostname` and rebooting, or you can just run +`hostname example.org` to change it temporarily for testing. Either way, +this will allow us to run the `mail` command as in [the SMTP +article](../smtp). + +```sh +echo "Hi there. + +This is the text." | mail -s "Email from the server" your@emailaddress.com +``` + +### More helpful troubleshooting. + +You can also go to [this site](https://appmaildev.com/en/dkim), which +will help you troubleshoot any other DKIM problems if you mistyped +something. + +## DMARC + +DMARC (Domain-based Message Authentication Protocol) is a protocol designed +to give email domain owners the ability to protect their domain from +unauthorized use. + +Add the dmarc user: + + useradd -m -G mail dmarc + +Open up your registrar or DNS settings again, and make a new TXT record like +we did with DKIM, except now use the output from the following command: + + echo "_dmarc.$(cat /etc/mailname)" + echo "v=DMARC1; p=reject; rua=mailto:dmarc@$(cat /etc/mailname); fo=1" + +The first line is the Host field. The latter is the TXT value. + +### Sender Policy Framework + +Saving the easiest for last, we should add a TXT record for SPF, +an email-authentication standard used to prevent spammers from sending messages +that appear to come from a spoofed domain. + + cat /etc/mailname + IP4=<your VPS's IPv4 address> + IP6=<your VPS's IPv6 address> + echo "v=spf1 mx a:mail.$(cat /etc/mailname) ip4:$IP4 ip6:$IP6 -all" + +**Note**: previous versions of this guide didn't ask you to specify the `ip4` +and `ip6` mechanisms. If you don't include them, some email hosts (most +notoriously gmail) will not accept mail from your server. + +The `IP4` and `IP6` values should be the same as what you set your [PTR +records](../rdns) to. + +The output of `cat /etc/mailname` is the Host field. The output of the second command is the TXT value. + +Again, you can check [that site](https://appmaildev.com/en/spf) +to make sure your DKIM, DMARC, and SPF entries are valid. That's it! + +## Contribution + +- SPF mechanisms updated by Martin Chrzanowski \-- [website](https://m-chrzan.xyz), [donate](https://m-chrzan.xyz/donate.html) diff --git a/content/maintenance.md b/content/maintenance.md new file mode 100644 index 0000000..e028e68 --- /dev/null +++ b/content/maintenance.md @@ -0,0 +1,125 @@ +--- +title: "Maintaining a Server" +date: 2021-06-29 +tags: ["server"] +--- + +Here are some important topics you should be familiar with whenever you +are managing a server. + +## Keep packages up to date. {#update} + +All GNU/Linux distributions use package managers to easily be able to +install and update packages without manually downloading them. On +Debian, which we use here for these tutorial the package manager is +`apt-get` or `apt` for short. + +It\'s a good idea to use `apt` to keep your software reasonably up to +date. + +```sh +apt update +apt upgrade +``` + +Not only do up-to-date packages often come with more features, but they +can also fix any possible security bugs. + +## Troubleshooting general problems + +Often when you are installing something new, you might miss a step and +run into an error, so it\'s important to know how to check and see what +errors have happened on your computer. + +On Debian and other GNU/Linux distributions that use systemd (most of +them), you can use the command `journalctl` to look at the system\'s +general log. You will probably want to run `journalctl -xe` as the `-x` +and `-e` as that gives the most information and starts you at the bottom +of the log to see the most recent errors. + +Some programs do not use this system log, but have their own logs stored +in `/var/log/`, or sometimes it\'s more convenient to look at a specific +program\'s log to see only its issues. + +For example, we can see that in `/var/log/nginx/`, nginx produces both +`error` and `access` files. The `access` files show you all the times +people connect to files on your server and much more. We can look at the +most recent errors by running: + +```sh +tail -n 25 /var/log/nginx/error.log +``` + +The command `tail -n 25` means \"show me the last 25 lines of this +file.\" You can replace that with `less` to browse the whole file. In +`less`, navigate with arrows or vim-keys and exit with `q`. + +### systemctl + +Another tool on systemd distributions is `systemctl`. At a basic level, +use `systemctl status put-service-name-here` to see if a system service +is running and its most recent log. But there\'s much more to +`systemctl`. + +For example, you can run `systemctl stop nginx` to stop NginX and +`systemctl start nginx` to start it back up (or use `restart` for both). +When you make changes to a program\'s configuration files, `reload` well +make them reload them. If you no longer want a service to start when the +system is rebooted, use `disable`, or conversely, to make a service +start on reboot use `enable`. + +## Finding Files + +Especially if you\'re new to how a GNU/Linux system is arranged, you +might need help finding files. To find program-related files, you can +just use `whereis`: + +```sh +$ whereis nginx +nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz +``` + +This command lists the directories related to that program. For example, +`/etc/nginx` is where the configuration files are and `/usr/share/nginx` +is where the library and module-like files are. + +But `whereis` can be used only with installed programs. A more general +tool is the pair of `updatedb` and `locate`. + +`updatedb` is a command that quickly indexes every file and directory on +your computer. Then you can run `locate` to find a file containing a +given name. After running `updatedb`, try running `locate nginx` to find +all files with \"nginx\" in their name. + +You can make your search more specific by chaining other Unix commands +through pipes. For example, `grep` takes input and returns only lines +that match an extra argument. In the example below, we `locate` all +files with \"nginx\" in the name, but we use `grep` to only show us +those with the word \"available\" in them. + +```sh +root@sich:~# locate nginx | grep available +/etc/nginx/modules-available +/etc/nginx/sites-available +/etc/nginx/sites-available/default +/etc/nginx/sites-available/sich +/usr/share/nginx/modules-available +/usr/share/nginx/modules-available/mod-http-auth-pam.conf +/usr/share/nginx/modules-available/mod-http-dav-ext.conf +/usr/share/nginx/modules-available/mod-http-echo.conf +/usr/share/nginx/modules-available/mod-http-geoip.conf +/usr/share/nginx/modules-available/mod-http-image-filter.conf +/usr/share/nginx/modules-available/mod-http-subs-filter.conf +/usr/share/nginx/modules-available/mod-http-upstream-fair.conf +/usr/share/nginx/modules-available/mod-http-xslt-filter.conf +/usr/share/nginx/modules-available/mod-mail.conf +/usr/share/nginx/modules-available/mod-stream.conf +``` + +`updatedb` is an ideal candidate for a [cronjob](/cron) so you +don\'t have to worry about running each time. For example, adding the +following to your crontab will run `updatedb` every 30 minutes: + +```sh +*/30 * * * * /usr/bin/updatedb +``` diff --git a/content/matrix.md b/content/matrix.md new file mode 100644 index 0000000..1fc4e92 --- /dev/null +++ b/content/matrix.md @@ -0,0 +1,241 @@ +--- +title: "Matrix Synapse" +date: 2021-07-16 +icon: "element.svg" +tags: ["service"] +short_desc: "An encrypted chat server sleek and accessible even to normies." +--- + +Matrix is easy-to-use, decentralized and encrypted private chat software. Matrix is federated, meaning that with a Matrix account on any server, including your own, you can talk to any other Matrix account on +the internet, similar to email. Matrix also allows fully end-to-end encrypted group chats. + +**Synapse** is the name of the default Matrix server. It is written in Python. While it is requires somewhat more system resources than [an XMPP server](/prosody), it makes up for that in being very accessible to non-technical users. + +## Installation + +The latest version of Synapse is not in the Debian package repositories by default, but we can easily add Matrix's repository including it: + +```sh +apt install -y lsb-release wget apt-transport-https +wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg +echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/matrix-org.list +``` + +After we update our packages lists, we will be able to install Synapse with `apt`. + +```sh +apt update +apt install matrix-synapse-py3 +``` + +When prompted, give your main domain name (not a subdomain). This will be the domain appended to your Matrix address, e.g. `@chad:{{<hl>}}chad.thesiah.xyz{{</hl>}}`. (_If you want to run Synapse under a different subdomain than the actual server name,_ then you must set up [delegation.](https://matrix-org.github.io/synapse/latest/delegate.html)) + +## Nginx configuration + +Create an Nginx configuration file for Matrix, say `/etc/nginx/sites-available/matrix` and add the content below: + +```nginx +server { + server_name {{<hl>}}matrix.example.org{{</hl>}}; + + listen 80; + listen [::]:80; + + listen 443 ssl http2 default_server; + listen [::]:443 ssl http2 default_server; + + listen 8448 ssl http2 default_server; + listen [::]:8448 ssl http2 default_server; + + location ~* ^(\/_matrix|\/_synapse|\/_client) { + proxy_pass http://localhost:8008; + proxy_set_header X-Forwarded-For $remote_addr; + client_max_body_size {{<hl>}}50M{{</hl>}}; + } + + # These sections are required for client and federation discovery + # (AKA: Client Well-Known URI) + location /.well-known/matrix/client { + return 200 '{"m.homeserver": {"base_url": "https://{{<hl>}}matrix.example.org{{</hl>}}"}}'; + default_type application/json; + add_header Access-Control-Allow-Origin *; + } + + location /.well-known/matrix/server { + return 200 '{"m.server": "{{<hl>}}matrix.example.org{{</hl>}}:443"}'; + default_type application/json; + add_header Access-Control-Allow-Origin *; + } +} +``` + +Note the `client_max_body_size` variable. By default, Nginx caps the size of files it can transfer. We increase that to 50M if needed by Matrix. (Note however that both Matrix and Nginx have seperate settings for this and to raise it to something much larger, you will have to increase the value in both configuration files.) + +Now let's enable the Nginx Matrix site and run **certbot** to get an encryption certificate and restart Nginx. + +```sh +ln -s /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled +certbot --nginx -d {{<hl>}}matrix.example.org{{</hl>}} +``` + +## Configuration + +### Read the config file + +The configuration file for Matrix is in `/etc/matrix-synapse/homeserver.yaml`. It is well documented and +commented, so you can read about the settings, but let's change the essential ones here. + +Make what changes you want and run `systemctl reload matrix-synapse` to make the system configuration active. + +### Database Setup + +Synapse, like [PeerTube](/peertube) and [Prosody](/prosody), supports **PostgreSQL** as a database backend. This can **significantly increase performance,** epsecially if you're already running PostgreSQL to run any other services. + +Begin by installing PostgreSQL: + +```sh +apt install postgresql +``` + +Then start the daemon: + +```sh +systemctl restart postgresql +``` + +Now create a user named `synapse_user` to manage your database: + +```sh +su -c "createuser --pwprompt synapse_user" postgres +``` + +And finally, create the actual database: + +```sh +su -c "psql -c 'CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse_user;'" postgres +``` + +Now edit the database configuration in `/etc/matrix-synapse/homeserver.yaml` and comment out the following lines for the previous SQLite configuration: + +```yml +# database: +# name: sqlite3 +# args: +# database: DATADIR/homeserver.db +``` + +_Note: The example above is how yours should look like after it's commented out._ + +Then, uncomment the following configuration above, and set the appropriate entries: + +```yaml +database: + name: psycopg2 + args: + user: {{<hl>}}synapse_user{{</hl>}} + password: {{<hl>}}secretpassword{{</hl>}} + database: {{<hl>}}synapse{{</hl>}} + host: localhost + cp_min: 5 + cp_max: 10 +``` + +Ensure that `synapse` is set to your database name, `synapse_user` is set to that database's owner, and that `secretpassword` is set to that user's password. + +### Adding Users and Admins + +If you allow open registration on your server in the configuration file, you can create an account through Element or another Matrix client, but you are probably going to want an official admin account to use. To make one, simply run the following command, which will then give you several choices for creating a user, among which will be the ability to make it an admin. + +Before setting up the admin user, make sure to set a `registration_shared_secret` in `/etc/matrix-synapse/homserver.yaml`: + +```yaml +registration_shared_secret: {{<hl>}}???{{</hl>}} +``` + +Then, run the following command to register a user: + +```sh +register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml +``` + +This command will prompt you for a username, password and whether to make the user an admin or not. + +### Voice and Video Calls + +For native voice and video call support, the Synapse homserver needs to interface with a working **TURN and STUN Server.** + +First, follow the guide on installing and setting up [coturn](/coturn), setting either a shared secret or username-password pair for authentication. + +Then, in `/etc/matrix-synapse/homeserver.yaml`, edit the configuration as follows: + +```yaml +turn_uris: + [ + "turn:{{<hl>}}turn.example.org{{</hl>}}?transport=udp", + "turn:{{<hl>}}turn.example.org{{</hl>}}?transport=tcp", + ] + +## This is how long call credentials are valid. Lessen to prevent abuse. +turn_user_lifetime: 86400000 + +## Keep this enabled unless for security reasons. +turn_allow_guests: True +``` + +If you're using a shared secret, add the following config: + +```yaml +turn_shared_secret: "{{<hl>}}your secret here{{</hl>}}" +``` + +Otherwise, add this config if you're using username-password pairs: + +```yaml +turn_username: "{{<hl>}}turnserver_username{{</hl>}}" +turn_password: "{{<hl>}}turnserver_password{{</hl>}}" +``` + +### URL Previews + +To enable server-generated previews of webpages, change this line to true in `/etc/matrix-synapse/homeserver.yaml`: + +```yaml +url_preview_enabled: true +``` + +And **make sure to uncomment** the `url_preview_ip_range_blacklist:` section; Otherwise, Synapse will refuse to start up again! + +### Federation + +Using the Nginx configuration provided with this guide, federation should work out of the box with Synapse. You can test whether it's working using the [Matrix Federation Tester.](https://federationtester.matrix.org/) + +However, some extra features can be enabled to increase the usability of your homeserver over federation. In `/etc/matrix-synapse/homeserver.yaml`, the following lines can be edited: + +```yaml +allow_public_rooms_over_federation: true +``` + +This can be un-commented to allow users to add your homserver to their list of servers (in a client like Element) and see a list of all the public rooms. + +```yaml +allow_public_rooms_without_auth: true +``` + +This can be un-commented to enable guests to see public rooms without authenticating. + +## Using Matrix with Element + +There are many different [clients](https://matrix.org/clients/) that can be used on desktops or phones to chat on your Matrix server, but the most popular and most widely vetted is Element. + +Get Element to access your Matrix server: + +- Mobile: + - [F-droid](https://f-droid.org/packages/im.vector.app/) + - [Google Play](https://play.google.com/store/apps/details?id=im.vector.app) + - [Apple App Store](https://apps.apple.com/app/vector/id1083446067) +- Real computer: + - GNU/Linux: You know how to install it. + - [Windows](https://packages.riot.im/desktop/install/win32/x64/Element%20Setup.exe) + - [Mac](https://packages.riot.im/desktop/install/macos/Element.dmg) + +Note also that Element has a web client (i.e. a version that can be accessed on your own website) that is also easy to install on an Nginx server, although that will be covered in another article. diff --git a/content/monero.md b/content/monero.md new file mode 100644 index 0000000..87f1d78 --- /dev/null +++ b/content/monero.md @@ -0,0 +1,89 @@ +--- +title: "Monero" +icon: 'xmr.svg' +date: '2021-06-29' +tags: ['service'] +short_desc: "The ideal private cryptocurrency for the Internet." +--- +Monero (abbreviated XMR) is easily the cryptocurrency most actually used +as such. Unlike Bitcoin, Monero is actually private and has very low +transaction fees. That makes it a good idea to get a Monero wallet and +add an address on your website where you can receive donations. + +## Generate a Monero wallet + +Go to [Monero\'s official site](https://www.getmonero.org/downloads/) and you can download either the GUI (graphical) or CLI (command-line +wallet). Some Linux distributions will have these packages in their +repositories (`monero` and `monero-gui` on Arch-based distributions). + +<aside> + +If you are a Windows user, note that you will *probably* get some kind +of warning that you are installing something malicious. This is because +many malicious pieces of software include crypto miners in them. This +wallet, obviously, does include one as well, because it has the ability +to mine if you want. You can disregard these messages and as that +official site mentions, you can follow their directions to check the +integrity of the download with SHA256. + +</aside> + +Once you install and run the wallet program, you will get a menu like +this: + +{{< img src="/pix/monero-01.png" alt="simple mode" >}} + +Now if you want to start using Monero and using it as a pro, you can +choose to download the whole blockchain which will maximize your +transactional privacy, however for this tutorial or setting up a wallet, +we can just do the Simple Mode and save our bandwidth. **In fact, if you +are paranoid, you can disconnect your computer from the internet while +generating a wallet.** + +Now we choose to create a wallet. + +{{< img src="/pix/monero-02.png" alt="create wallet" >}} + +Now we get the most important and sensitive part, you private mneumonic +seed. **These words are sacred! They are your money!** To be clear, they +are randomly generated words that seed the randomness required to unlock +whatever money you receive or hold. Never show these words to anyone, +don\'t even keep them on your computer, but write them down and store +them securely in real life in a safe or somewhere where only you have +access. + +{{< img src="/pix/monero-03.png" alt="seed" >}} + +It goes without saying that the seed above that we generated for this +tutorial should never be used by anyone since it is public on the +internet and anyone could easily take the funds from the wallet. + +Finally, we get to the main wallet screen. Now we see your public +sharable wallet receiving address. It is the thing that starts with `4` +and is too long to be included in the image below labeled \"Primary +address.\" + +{{< img src="/pix/monero-04.png" alt="address" >}} + +Click the clipboard next to it to copy the whole sequence (which will be +more than 90 letters and numbers) to your clipboard. This is your +address. Put it on your website and you can receive donations! + +You can also click to save that QR code image and you can put it up on +your website and people will be able to scan it and send you Monero. +When scanned, that QR code will read as the public donation address. + +## What do I do now? + +You can now receive Monero/XMR donations! All you need to do is put +either your full address or your QR code on your site and people can +send you tips in Monero. + +Here is the address we use for this site (i.e. not the compromised +wallet generated above): + +<code class=crypto>84RXmrsE7ffCe1ADprxLMHRpmyhZuWYScDR4YghE8pFRFSyLtiZFYwD6EPijVzD3aZiEpg57MfHEr1pGJNPXyJgENMnWrSh</code> + +{{< img src="/pix/xmr.png" class=qr alt="monero donation qr" >}} + +It\'s now up to you how and where to display these on your site. diff --git a/content/monerod.md b/content/monerod.md new file mode 100644 index 0000000..19afba0 --- /dev/null +++ b/content/monerod.md @@ -0,0 +1,233 @@ +--- +title: "Monero Node" +icon: 'xmr.svg' +date: '2021-06-29' +tags: ['service'] +short_desc: "Contribute to the Monero network." +--- + +The Monero cryptocurrency relies on a network of [decentralized nodes](https://www.getmonero.org/resources/moneropedia/node.html) to store the private transaction information and maintain consensus. + +Running your own node will let you relay transactions and contribute to the Monero network by dedicating storage and processing power to the task. You can then connect to your node from a wallet (if you enable rps). + +Some other benefits of a full node are: + +- More reliable and trusted as opposed to using a public node +- More secure for RPC calls for payment processors +- The ability to mine using [p2pool](https://p2pool.io/#help) +- The ability to run a mining pool or solo mine\* + +**Note: Solo mining can be very unreliable and it is not recommended unless you have a very powerful computer.* + +**Warning:** Running a Monero node requires *a lot of storage* (at least 100GB) and a reasonable amount of memory and processing power. If you are hosting at home, make sure to use an **SSD** and not a hard disk drive, as advised by `monerod`. + +## Installation + +Because of the nature of Monero as an ever-evolving decentralized project, it is advised to download and keep an up-to-date version of it for your node. This can be accomplished by downloading the software manually: + +```sh +wget https://downloads.getmonero.org/linux64 +tar -xvjf linux64 +mv linux64/monero* /usr/bin/ +``` + +If the hardware you are using is not based on the amd64 architecture (like a Raspberry Pi), the monero project also [offers binaries](https://www.getmonero.org/downloads/) for other architectures on Linux, to download and install them simply change the last part of the link (linux64) and the archive name, e.g. for arm64 (linuxarm8). The fastest way to find out which one to use in Debian is with the `dpkg --print-architecture` command. + +## Configuration + +By default, Monero comes with no sample configuration files. Create one in `/etc/monerod.conf` using a text editor, and enter the following details: + +```sh +# Configuration for monerod +# Syntax: any command line option may be specified as 'clioptionname=value'. +# Boolean options such as 'no-igd' are specified as 'no-igd=1'. +# See 'monerod --help' for all available options. + +data-dir={{<hl>}}/var/lib/monero{{</hl>}} +log-file={{<hl>}}/var/log/monero/monero.log{{</hl>}} +log-level=0 + +# Slow but reliable db writes +db-sync-mode=safe + +# 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network +limit-rate-up=1048576 +limit-rate-down=1048576 + +# Be more generous to wallets connecting +disable-rpc-ban=1 +``` + +### Log files + +The logfile at `/var/log/monero/monerod.log` will get **very large, very soon** if you do not limit it's size. Add these options to `/etc/monerod.conf` to limit it's size, and limit the creation of additional log + backups: + +```sh +# Limit log size to 10 MiB +max-log-file-size=10485760 +max-log-files=5 +``` + +### Making a Public Node + +To advertise and let other users connect to your node, enable the following options: + +```sh +restricted-rpc=true +# Bind to all addresses (useful if under NAT) +p2p-bind-ip=0.0.0.0 +rpc-bind-ip=0.0.0.0 +confirm-external-bind=1 + +public-node=true +``` + +### User creation + +Create a dedicated user to run `monerod` named `monero`: +```sh +useradd -m -d /var/lib/monero monero +``` + +Create the directories, and ensure the user has the relevant permissions on them: +```sh +mkdir /var/lib/monero && chown -R monero:monero /var/lib/monero +mkdir /var/log/monero && chown -R monero:monero /var/log/monero +``` + +### Pruning the blockchain + +When running a node, [pruning](https://www.getmonero.org/resources/moneropedia/pruning.html) allows the user to save data by only storing 1/8th of the ring signature information. Every "pruned" node contains a random 1/8th of the data, so the information is never lost. While this isn't as helpful to the network as running a full node, it is a very reasonable option when storage space and bandwidth are limited. **A pruned node will only use 1/3rd of storage compared to a full node.** + +To enable pruning, add the following options to `/etc/monerod.conf`: +```sh +prune-blockchain=true +# This option should speed up the syncing process +sync-pruned-blocks=true +``` + +## Tor/I2P Setup + +from the Monero documentation: + +> Only handshakes, peer timed syncs and transaction broadcast messages are supported over anonymity networks. + +Monero nodes **cannot sync the blockchain over Tor or I2P,** but the node can broadcast transactions and *let users connect* over these anonymizing networks. + +To set this up, first install [Tor](/tor) and/or [I2P](/i2p). + +When creating a hidden service, create the following configuration: + +### Tor + +Edit `/etc/tor/torrc` and add the following: + +```sh +HiddenServiceDir /var/lib/tor/monerod + +# For wallets connecting over RPC: +HiddenServicePort 18081 127.0.0.1:18181 +# For other nodes: +HiddenServicePort 18083 127.0.0.1:18183 +``` + +Now restart Tor: +```sh +systemctl restart tor +``` + +You can acquire the Tor address by running: +```sh +cat /var/lib/tor/monerod/hostname +``` + +### I2P + +Edit `tunnels.conf` (Which may be located in `/etc/i2pd/` if you followed [this](/i2p) guide) and add the following tunnels: + +```systemd +[monerod] +type = http +host = 127.0.0.1 +port = 18283 +keys = monerod.dat + +[monerod-rpc] +type = http +host = 127.0.0.1 +port = 18281 +keys = monerod-rpc.dat +``` + +Now restart `i2pd`: +```sh +systemctl restart i2pd +``` + +You can acquire the I2P address by running: +```sh +printf "%s.b32.i2p +" $(head -c 391 /home/i2p/.i2pd/monerod.dat | sha256sum |xxd -r -p | base32 | sed s/=//g | tr A-Z a-z) +``` + +### Configuring monerod + +Then, in `/etc/monerod.conf`, add the following: + +```sh +# Tor config +tx-proxy=tor,127.0.0.1:9050,10 +anonymous-inbound={{<hl>}}your-tor-address-here.onion{{</hl>}}:18083,127.0.0.1:18183,16 + +# I2P config +tx-proxy=i2p,127.0.0.1:4447 +anonymous-inbound={{<hl>}}your-i2p-address-here.b32.i2p{{</hl>}}:80,127.0.0.1:18283,16 # Maximum 16 simultaneous connections +``` + +## Running the Node + +Then, run this command to download the systemd daemon configuration for `monerod`. This will allow your node to run in the background and start automatically on boot as a service. + +```sh +curl https://raw.githubusercontent.com/monero-project/monero/master/utils/systemd/monerod.service > {{<hl>}}/etc/systemd/system/monerod.service{{</hl>}} +``` + +*Note: This configuration assumes that you've created a user named `monero` which runs the program `monerod` in it's home directory, and which points to the configuration in `/etc/monerod.conf`. Edit any of these details in `/etc/systemd/system/monerod.service` if they don't apply to your configuration.* + +Now reload the systemd service file: +```sh +systemctl daemon-reload +``` + +To run the node, restart the systemd service: +```sh +systemctl restart monerod +``` + +To monitor the node's status at any time (for example, to check sync progress) check the log file using `tail`: +```sh +tail -f /var/log/monero/monerod.log +``` + +## Connecting to your Node + +To connect to your node using the GUI wallet, first open it: + +{{< img src=/pix/monerod/monerod-step-1.webp >}} + +On the mode selection screen, make sure to pick **Advanced mode:** + +{{< img src=/pix/monerod/monerod-step-2.webp >}} + +When you reach daemon settings, select the **Connect to a remote node** option, and then click **add remote node.** + +{{< img src=/pix/monerod/monerod-step-3.webp >}} + +A prompt will appear, asking for your node's details. Add your **address,** set the port to **18081,** and make to click **Mark as trusted daemon.** + +{{< img src=/pix/monerod/monerod-step-4.webp >}} + +When you reach the main wallet screen, you'll see **"Remote Node"** in the bottom-left corner. Now you can enjoy using your Monero node straight from your wallet! + +{{< img src=/pix/monerod/monerod-step-5.webp >}} diff --git a/content/movim.md b/content/movim.md new file mode 100644 index 0000000..8743b81 --- /dev/null +++ b/content/movim.md @@ -0,0 +1,116 @@ +--- +title: "Movim" +draft: true +icon: 'movim.svg' +tags: ['service'] +short_desc: 'An XMPP-based social media site, blog and chat site.' +--- +## Installing the Packages and Database + +### Dependencies + + apt install -y nginx python3-certbot-nginx postgresql composer php-fpm php-curl php-mbstring php-imagick php-gd php-pgsql php-xml git + +### Installing Movim Itself + + cd /var/www + git clone https://github.com/movim/movim.git + cd movim + composer install + +### Preparing Permissions + + cd /var/www + chown www-data movim && chown www-data movim/public && chmod u+rwx movim + +### Database setup + + su - postgres # Become the postgres user + psql # Open a postgresql prompt + CREATE USER movim WITH PASSWORD 'yourpassword' ; + CREATE DATABASE movim WITH OWNER movim ; + \q + +leave postgres user + +We now have to tell movim to use this newly created postgresql username +and database that we\'ve created. Create a new file in +`/var/www/movim/config/db.inc.php` and add the following content: + + <?php + $conf = [ + 'type' => 'pgsql', + 'username' => 'movim', + 'password' => 'yourpassword', + 'host' => 'localhost', + 'port' => 5432, + 'database' => 'movim' + ]; + +ask for pass https://movim.yourdomain.com Choose postgresq localhost +pass + +## Configuration with nginx + +Let\'s create an nginx configuration file for this movim site. I will +create a file `movimsite.conf` in `/etc/nginx/sites-available/` and add +the following content: + + server { + listen 80 ; + listen [::]:80 ; + server_name movim.lukesmith.xyz ; + include /etc/nginx/snippets/movim.conf ; + location / { + try_files $uri $uri/ =404; + } + } + +Note above that this is calling the file +`/etc/nginx/snippets/movim.conf` which contains the content needed for +Movim and should be autocreated when installing the Debian package. + +To enable the site, let\'s link the file to the `sites-enabled` +directory and then reload nginx to update it. + + ln -s /etc/nginx/sites-available/movimsite.conf /etc/nginx/sites-enabled/ + systemctl reload nginx + +Now, run [certbot](/basic/certbot) which we installed above to get secured +connections on your site. Choose to \"Redirect\" unencrypted connections +when prompted. + + certbot --nginx + +## Systemd service + +Let\'s create a systemd service for Movim. Create the file +`/etc/systemd/system/movim.service` and add the content below: + + [Unit] + Description=Movim daemon + After=nginx.service network.target local-fs.target + + [Service] + User=www-data + Type=simple + Environment=PUBLIC_URL=https://localhost/movim/ + Environment=WS_PORT=8080 + EnvironmentFile=-/etc/default/movim + ExecStart=/usr/bin/php daemon.php start --url=${PUBLIC_URL} --port=${WS_PORT} + WorkingDirectory=/var/www/movim/ + StandardOutput=syslog + SyslogIdentifier=movim + PIDFile=/run/movim.pid + Restart=on-failure + RestartSec=10 + + [Install] + WantedBy=multi-user.target + + systemctl daemon-reload + systemctl restart movim + +Install prosody modules apt install mercurial mkdir -p +/usr/share/prosody hg clone https://hg.prosody.im/prosody-modules/ +/usr/share/prosody/modules diff --git a/content/mumble.md b/content/mumble.md new file mode 100644 index 0000000..19bbd00 --- /dev/null +++ b/content/mumble.md @@ -0,0 +1,144 @@ +--- +title: "Mumble" +icon: 'mumble.svg' +tags: ['service'] +date: 2023-07-02 +short_desc: 'Open Source, Low Latency, High Quality Voice Chat.' +--- + +[Mumble](https://mumble.info) is an open source, low latency and high quality voice chat software, being the best open source alternative to TeamSpeak. +VoIP communications are mandatory encrypted by default using OCB-AES128, it has integrations for gamers (like overlays), it's stable and it's resource friendly. + +The server can also be run [behind Tor](https://gitlab.torproject.org/legacy/trac/-/wikis/doc/TorifyHOWTO/Mumble) without any issue. + +## Installation + +Mumble has a Debian repository for client and server, however it's very outdated so we are going to build the server instead. + +**I suggest to build both binaries on your local machine and [transfer the `mumble-server` to your remote server using `scp`](#extra).** + + +Install dependencies: +```sh +apt install build-essential cmake pkg-config qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qttools5-dev qttools5-dev-tools libqt5svg5-dev libboost-dev libssl-dev libprotobuf-dev protobuf-compiler libprotoc-dev libcap-dev libxi-dev libasound2-dev libogg-dev libsndfile1-dev libspeechd-dev libavahi-compat-libdnssd-dev libxcb-xinerama0 libzeroc-ice-dev libpoco-dev g++-multilib +``` + +Git clone the repo. + +```sh +git clone https://github.com/mumble-voip/mumble.git && cd mumble +``` + +Initialize all the submodules. + +``` +git submodule update --init +``` + +Create a build directory and run `cmake`. +Cmake will create all the necessary files to build the mumble-server and client. + +```sh +mkdir build && cd build && cmake .. +``` + +Build using `cmake`. + +```sh +cmake +``` + +After the build you will now find a file named `mumble-server`, one `mumble` (which is the client) and a file named `mumble-server.ini` (aka the config file). + +## Running your Mumble server + +If you built it on local machine you can check out [how to move it to your remote server](#extra) first. + +After that, start with making your `mumble-server` executable and move it in `/usr/bin`. + +```sh +chmod +x mumble-server && mv mumble-server /usr/bin +``` + +Create a folder in `/etc/` move your config files there. + +```sh +mkdir /etc/mumble && mv mumble-server.ini /etc/mumble +``` + +By default, mumble-server uses port 64738, so make sure to open that port on your firewall (if you're using one), or whatever other port you selected on your configuration file. If you're using `ufw` as your firewall, the command is: + +```sh +ufw allow 64738 +``` + +Now we can run the server passing the config and a superuser password that can be used to connect and authenticate as an administrator from any client + +```sh +mumble-server -ini mumble-server.ini -supw <your_password> +``` + +Check if it's running in the backgroud with `ps aux`. + +```sh +ps aux | grep mumble-server +``` + +You will have an output like this. + +```sh +root 127181 0.1 0.1 261064 21640 ? Sl 19:18 0:01 ./mumble-server +root 127689 0.0 0.1 112956 22572 ? Sl 19:19 0:00 ./mumble-server +``` + +## Connecting to your mumble-server as a SuperUser + +You will probably will be left with your `mumble` binary in the build folder on your local machine. + +Now you should make it executable and move it in the `/usr/bin` folder. + +```sh +chmod +x mumble && mv mumble /usr/bin +``` + +Run it the GUI with one command. + +```sh +mumble +``` + +You will have something like this opening up. + +{{< img src="/pix/mumble/mumble-1.png" alt="connect window" >}} + +Click on the button `Add New...` and fill out the information need to connect to your server. + +{{< img src="/pix/mumble/mumble-2.png" alt="add server window" >}} + +If you haven't edited the port, `64738` will be default one. + +Click on `Ok`, select your server from the list and click `Connect`. + +**Now you are connected to your very own Mumble server as a SuperUser!** + +Now, you will want to setup a regular user to be an administrator of the server. Follow the [official documentation](https://wiki.mumble.info/wiki/Murmurguide#Becoming_Administrator_and_Registering_a_User) in order to do that, it is well-explained, so I won't repeat it here. + +Also, you might want to take a look at the [options for your config file](https://wiki.mumble.info/wiki/Murmurguide#Set_Up_Server), since mumble let's you set up a good amount of things, including a server password, a welcome message, and how to make your server public for the whole internet to see. + +--- + +## Extra + +### Move binary with scp + +Move your binary to the folder `~` of your remote server. + +```sh +scp <your_binary> root@<your_server_ip>:~ +``` + +--- + +Written by [NotMtth](https://notmtth.xyz) (Tor access warning) + +Donate Monero at: `donate.notmtth.xyz` ([OpenAlias](https://openalias.org/)) diff --git a/content/networking.md b/content/networking.md new file mode 100644 index 0000000..550f978 --- /dev/null +++ b/content/networking.md @@ -0,0 +1,336 @@ +--- +title: Networking Basics +date: 2022-07-01 +tags: ['concepts'] +--- + +## A quick detour to binary + +You probably know that everything computers do, they do in binary +(zeroes and ones) under the hood. But how does that actually work? + +Binary is just another numbering system like decimal (there are many +others!), so while with decimal each digit can have 10 different values +(0-9, hence **deci**mal), numbers represented in binary have 2 possible +values (0-1, hence **bi**nary). In binary a digit is called a bit. + +What is the highest number you can represent with one digit in decimal? +Easy: 9. So how many different values are there? 10 (0-9). + +What about 2 digits? 99 and 100, respectively. 3 digits? 999 and 1000. +I\'m sure I don\'t need to bore you by continueing. + +### The maths behind it + +Can we define a formula for the amount of possible values a decimal +number with `n` digits can have? + +It\'s pretty easy: <code>10<sup>n</sup></code>. + +Now the 10 there in a numbering system where each digit can have 10 +different values can\'t be a coincidence! + +So we can generalize: In a numbering system where each digit can have +`x` different values, the amount of possible values for a number with +`n` digits is <code>x<sup>n</sup></code>. + +So how many different values can we represent with 8 Bits (1 Byte)? +<code>2<sup>8</sup> = 256</code> (0-255). + +The IPv4 addresses you know are 32 bits long. So how many computers +could we theoretically assign unique IPs to on the internet? +<code>2<sup>32</sup> = 4,294,967,296</code>. That\'s 4 Billion! However there are far more +computers than that on the internet now, which is why people had to come +up with hacks (which we\'ll talk about later) so that we can today still +predominantly use pretty IPv4, as opposed to that ugly new IPv6 (eww). + +We\'ll say \"IP address\" instead of \"IPv4 address\" from here on. + +By the way, this principle goes a long way in computing! Say, for +example, I know your password is 7 letters long and contains only +lowercase english letters (a-z). How many times would I have to guess at +maximum to crack your password? <code>25<sup>7</sup> = 6,103,515,625</code> times. + +### Converting from binary to decimal + +You can use the same principle to convert from one numbering system to +another. Each digit gains \"significance\", starting at zero going from +right to left. This is easiest understood through an example from +decimal: + +<pre><code>943 = 9*10<sup>2</sup> + 4*10<sup>1</sup> + 3*10<sup>0</sup> = 900 + 40 + 3 = 943</code></pre> + +The same holds true for binary: + +<pre><code>11001101 = 2<sup>7</sup> + 2<sup>6</sup> + 2<sup>3</sup> + 2<sup>2</sup> + 2<sup>0</sup> = 128 + 64 + 8 + 4 + 1 = 205</code></pre> + +### The binary behind IP addresses + +As mentioned, IP addresses are made up of 32 bit, or 4 byte. IP +addresses are usually represented in \"dotted-decimal\" notation, where +we write the decimal value of the first byte (left-to-right), a dot, +then the decimal value of the second byte, etc. + +So, in theory, the lowest possible IP address is `0.0.0.0` (all bits are +0) and the highest possible IP address is `255.255.255.255` (all bits +are 1). + +## Subnetting + +Open up a terminal and run + +```sh +ip a +``` + +You should see many names, such as `wlan*` or `wlp*` for wireless +interfaces or something like `eth*` or `enp*` for ethernet interfaces. +I\'ve used a new word here: \"interfaces\", we\'ll talk more about what +those are later. + +Here\'s my WiFi interface: + +{{< img alt="wifi interface" src="/pix/networking-wlan0.png" link="/pix/networking-wlan0.png" >}} + +We can see an IP address, `192.168.1.221`, and another one which we\'ll +ignore for now. Did I just leak my IP address? No, it is only my local +IP, it could even be that yours is the same as mine! + +There are two reasons for this: + +1. There is a [list of IP address + ranges](https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4) + reserved for you to use however you want, here in local networking. + You will not find a server on the internet that has an IP in one of + those ranges. +2. The hack to get around the limitations of IPv4 I mentioned earlier + is [NAT (Network Address + Translation)](https://en.wikipedia.org/wiki/Network_address_translation). + Your router gives every device in your local network one of those + reserved IPs and manages one public IP towards the internet for all + of them. So instead of every device needing one of those 4 Billions + IPs, only every house needs one. And some ISPs take this a level + further and again put multiple houses under one NAT, so multiple + houses can share one IP towards the internet (Carrier-Grade NAT). + +If you followed the link for reserved IP address ranges or looked closer +at my screenshot, you will see IP addresses followed by a slash and then +some number, here `/24`. This is how we denote IP ranges in networking, +the so-called CIDR-Notation. The first ip address in the range is the +**Network ID** and the number after the slash is the **subnet mask**. It +might look strange at first, but makes a lot of sense: The subnet mask +is the amount of bits **fixed**. So here in my case the first 24 bits (3 +bytes) are fixed and my local network\'s IP range, also called +**subnet**, goes from `192.168.1.0` to `192.168.1.255`. + +Here are two popular reserved subnets and their IP ranges: + +``` +192.168.0.0/16: 192.168.0.0 – 192.168.255.255 +10.0.0.0/8: 10.0.0.0 – 10.255.255.255 +``` + +Here\'s another popular one, but note that the subnet mask isn\'t +divisible by 8, so it is a bit less easy to deal with: + +``` +172.16.0.0/12: 172.16.0.0 – 172.31.255.255 +``` + +The way this works is the first byte is fully fixed, and then the first +4 bits of the second byte are fixed too, the rest is usable by us. So in +the second byte the last `8-4 = 4` bits are free. <code>2<sup>4</sup> = 16</code>, giving us +the actual highest number 15. We add this to the \"starting point\", the +current value of the second byte, and arrive at `16+15 = 31`! + +Don\'t worry if that last part about uneven subnet-masks was confusing +to you, you won\'t have to deal with them as a regular user. +Additionally there are websites where you can enter subnets and they do +the maths for you. + +## Interfaces + +I\'ve mentioned interfaces a few times now without really explaining +what they are. Generally you can think of interfaces as physical +networking devices. If you have a WiFi-Card in your computer, it will +get an interface. If you have an ethernet card, it will get another one. +If you now plug in something like a USB WiFi dongle, it will get another +interface. + +There are also virtual interfaces. For example if you run a virtual +machine with something like virt-manager, use containers with docker or +connect to a VPN through OpenVPN or WireGuard, all those get virtual +interfaces. + +We can assign IP addresses to interfaces and Linux then knows that when +it receives a packet who\'s recipient is that IP, it is meant for us. +Then later with routing we can tell Linux to send packets destined to, +say, `192.168.3.0/24`, to our ethernet interface, which will make Linux +send that data to the ethernet card, which will in turn send it through +the actual physical cable! + +Here\'s a bigger picture of the full output of `ip a` on my machine: + +{{< img alt="output of ip a" src="/pix/networking-interfaces.png" link="/pix/networking-interfaces.png" >}} + +We can see a few interfaces here: + +- `lo`: The loopback interface. A virtual interface that makes packets + to `127.0.0.1` go straight back to your own machine. +- `wlan0`: My WiFi interface. We can see its state is `UP`, I have the + IP `192.168.1.221` on the network and the subnet mask is `/24`. +- `virbr0`: My KVM interface. We can see its state is `DOWN`, I have + the IP `192.168.122.1` on the network and the subnet mask is `/24`. +- `wgpi`: An interface for the WireGuard connection I have to my + Raspberry Pi. I have the IP `10.91.0.2` on the network and the + subnet mask is `/24`. +- `wgnord`: An interface for the WireGuard connection I have to a + remote VPN server. I have the IP `10.5.0.2` on the network and the + subnet mask is `/32`. + +## Routing + +Okay, so we\'ve learned about interfaces now. Those don\'t do much by +themselves though, since right now Linux will never really use them. To +make use of them we need to use routing to tell Linux which packets it +should put into those interfaces. These definitions of what outgoing +traffic to put into which interfaces are called routes! + +To view the routes set up on your machine, run this command: + +```sh +ip r +``` + +Here\'s the command\'s output on my server: + +{{< img alt="output of ip r" src="/pix/networking-server-routes.png" link="/pix/networking-server-routes.png" >}} + +And here\'s an excerpt of the interfaces on my server: + +{{< img alt="network interface" src="/pix/networking-server-interfaces.png" link="/pix/networking-server-interfaces.png" >}} + +The first route containing `default via` is special: All packets that +don\'t match other routes are automatically sent to this interface +(`ens3`). Now you might remember `172.31.1.1` is in one of those +reserved subnets, so this isn\'t another machine on the internet! This +is my server\'s \"gateway\". At home your gateway probably is your +router: You send everything to it and it then forwards those packets to +the internet (or another device on your local network, if you\'re +speaking to another IP within your subnet). + +Note also that my server\'s `ens3` interface has an IP address assigned +which is not one of the reserved ones. Therefore my server isn\'t behind +NAT and this is the actual IP my server can be reached at on the +internet! Also note that the subnet mask is `/32`, or \"all bits in this +IP are fixed\". + +The second line is for the virtual interface created by docker. All +containers get assigned an IP within the subnet `172.17.0.0/16`, and +this route tells Linux to put packets destined for said subnet into the +`docker0` virtual interface, which then ends up at the container having +that IP. We can see some additional info too: The IP packet\'s source +will be set to `172.17.0.1` and the `linkdown` state signifies that we +have a route set up, but the interface for that route is in `DOWN` +state. + +## Putting it all into practice + +Now it might be interesting and all to know how Linux does networking, +but as a regular user you\'ve probably never had to touch the `ip` +command in the past: Your server comes set up out of the box and if you +connect to a WiFi, the interface and routes are configured automatically +for you. This is done by your network manager through +[DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol). + +Recently I\'ve had a use case where I had to configure networking +manually: I wanted to move around 200GB of data from one laptop to +another. Now there are a few ways I could go about this: I could look +for a big enough USB-Drive and move the data that way. Or I could +connect both devices to the same WiFi (they already were) and move the +data over the network using rsync, or sshfs, or scp, or nfs, \... But +the problem here is that my local WiFi is only about 100Mbit/s fast, +moving 200GB at that speed would take over 4 hours, if my math is +correct, and would congest the WiFi for all that time. But your standard +ethernet can do a stable 1Gbit/s, which would drop the time down to 26 +minutes! + +So I take an ethernet cable and directly connect both laptops with that. +On both machines `ip a` now shows something like this: + +{{< img alt="new output of ip a" src="/pix/networking-ethernet-unconfigured.png" link="/pix/networking-ethernet-unconfigured.png" >}} + +There is no DHCP-Server running on either machine, so we\'ll have to do +the configuring ourselves! From here on we\'ll have Computer A with +interface `eth0` and Computer B with interface `eth1`, for clarity. + +First we must choose what subnet our ethernet interface should use. We +can freely choose from the list of reserved subnets here, as long as the +subnet isn\'t occupied by another interface on either machine. We\'ll +say `192.168.50.0/24`. + +Note also that the first and last address on each subnet, here +`192.168.50.0` and `192.168.50.255`, respectively, can\'t actually be +assigned to any device. The first is called \"Network ID\", as mentioned +previously, and the last is called \"broadcast IP\". + +So we\'ll give Computer A the IP `192.168.50.1` and Computer B the IP +`192.168.50.2`. To do that we use the `ip` command aswell. + +Computer A: + +```sh +ip addr add 192.168.50.1/24 dev eth0 +``` + +Computer B: + +```sh +ip addr add 192.168.50.2/24 dev eth1 +``` + +It should look something like this now: + +{{< img alt="new ip addresses" src="/pix/networking-ethernet-ip.png" link="/pix/networking-ethernet-ip.png" >}} + +Now we change the interface\'s state to `UP`: + +Computer A: + +```sh +ip link set eth0 up +``` + +Computer B: + +```sh +ip link set eth1 up +``` + +It should look something like this now: + +{{< img alt="ethernet output" src="/pix/networking-ethernet-ip-up.png" link="/pix/networking-ethernet-ip-up.png" >}} + +Are we done? You can try pinging one IP from another. It won\'t work, +because we don\'t have routes set up yet. So lets\'s do that: + +Computer A: + +```sh +ip route add 192.168.50.0/24 dev eth0 +``` + +Computer B: + +```sh +ip route add 192.168.50.0/24 dev eth1 +``` + +You should see something like this in `ip r`: + +{{< img alt="ip routes final" src="/pix/networking-ethernet-route.png" link="/pix/networking-ethernet-route.png" >}} + +They are now able to talk to each other! + +## Contribution +- [phire](https://phire.cc) diff --git a/content/nextcloud.md b/content/nextcloud.md new file mode 100644 index 0000000..9ec7627 --- /dev/null +++ b/content/nextcloud.md @@ -0,0 +1,272 @@ +--- +title: "Nextcloud" +date: 2021-06-30 +icon: 'nextcloud.svg' +tags: ['service'] +short_desc: 'A free and private Google Drive-like cloud storage system.' +--- + +## What is Nextcloud? {#whatis} + +[Nextcloud](https://nextcloud.com) +is a free and open source solution for cloud storage. However it can +also do other things, such as manage your email, notes, calender, tasks, +and can even connect to the Fediverse (think Mastodon and Pleroma). +Pretty much every service that Google has to offer has a much better +alternative as a Nextcloud app and this is a must-have for anyone +wanting to get away from Google services but still wants a traditional +cloud experience (in the likes of Google Services, anyways). + +## Dependencies + +First, we install the dependencies: + +```sh +apt install -y nginx python3-certbot-nginx mariadb-server php php-{fpm,bcmath,bz2,intl,gd,mbstring,mysql,zip,xml,curl} +``` + +*Optionally*, you can improve the performance of your Nextcloud server by adjusting the child processes that are used to execute PHP scripts. That way, more PHP scripts can be executed at once. Make the following adjustments to `/etc/php/8.2/fpm/pool.d/www.conf`: + +```systemd +pm = dynamic +pm.max_children = 120 +pm.start_servers = 12 +pm.min_spare_servers = 6 +pm.max_spare_servers = 18 +``` + +Start the MariaDB server: + +```sh +systemctl enable mariadb --now +``` + +### Setting up a SQL Database + +Next, we need to set up our SQL database by running a Secure +Installation and creating the tables that will store data that Nextcloud +will need. Run the following command: + +```sh +mysql_secure_installation +``` + +We can say "Yes" to the following questions, and can input a root password. + +```sh +Switch to unix_socket authentication [Y/n]: Y +Change the root password? [Y/n]: Y # Input a password. +Remove anonymous users? [Y/n]: Y +Disallow root login remotely? [Y/n]: Y +Remove test database and access to it? [Y/n]: Y +Reload privilege tables now? [Y/n]: Y +``` + +Next, sign into the SQL database with the new and secure password you +chose before. Run the following command: + +```sh +mysql -u root -p +``` + +We need to create a database for Nextcloud. Follow the instructions +below and change some of the placeholders as you wish: + +```mysql +CREATE DATABASE nextcloud; +GRANT ALL ON nextcloud.* TO '<your_username>'@'localhost' IDENTIFIED BY '<your_password>'; +FLUSH PRIVILEGES; +EXIT; +``` + +### HTTPS + +As with any subdomain, we need to obtain an SSL certificate. + +```sh +certbot certonly --nginx -d nextcloud.example.org +``` + +### Nginx configuration + + +In `/etc/nginx/sites-available/` we need to make a new configuration for +Nextcloud (example: `/etc/nginx/sites-available/nextcloud`). + + +Add the following content [based of Nextcloud's recommendations](https://docs.nextcloud.com/server/25/admin_manual/installation/nginx.html) to the file, **remembering to replace `nextcloud.example.org` with your Nextcloud domain**. + +```nginx +upstream php-handler { + server unix:/var/run/php/php-fpm.sock; + server 127.0.0.1:9000; +} +map $arg_v $asset_immutable { + "" ""; + default "immutable"; +} +server { + listen 80; + listen [::]:80; + server_name nextcloud.example.org ; + return 301 https://$server_name$request_uri; +} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name nextcloud.example.org ; + root /var/www/nextcloud; + ssl_certificate /etc/letsencrypt/live/nextcloud.example.org/fullchain.pem ; + ssl_certificate_key /etc/letsencrypt/live/nextcloud.example.org/privkey.pem ; + client_max_body_size 512M; + client_body_timeout 300s; + fastcgi_buffers 64 4K; + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + client_body_buffer_size 512k; + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Download-Options "noopen" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-XSS-Protection "1; mode=block" always; + fastcgi_hide_header X-Powered-By; + index index.php index.html /index.php$request_uri; + location = / { + if ( $http_user_agent ~ ^DavClnt ) { + return 302 /remote.php/webdav/$is_args$args; + } + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + location ^~ /.well-known { + location = /.well-known/carddav { return 301 /remote.php/dav/; } + location = /.well-known/caldav { return 301 /remote.php/dav/; } + location /.well-known/acme-challenge { try_files $uri $uri/ =404; } + location /.well-known/pki-validation { try_files $uri $uri/ =404; } + return 301 /index.php$request_uri; + } + location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } + location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } + location ~ \.php(?:$|/) { + # Required for legacy support + rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + set $path_info $fastcgi_path_info; + try_files $fastcgi_script_name =404; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $path_info; + fastcgi_param HTTPS on; + fastcgi_param modHeadersAvailable true; + fastcgi_param front_controller_active true; + fastcgi_pass php-handler; + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + fastcgi_max_temp_file_size 0; + } + location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$ { + try_files $uri /index.php$request_uri; + add_header Cache-Control "public, max-age=15778463, $asset_immutable"; + access_log off; # Optional: Don't log access to assets + location ~ \.wasm$ { + default_type application/wasm; + } + } + location ~ \.woff2?$ { + try_files $uri /index.php$request_uri; + expires 7d; + access_log off; + } + location /remote { + return 301 /remote.php$request_uri; + } + location / { + try_files $uri $uri/ /index.php$request_uri; + } +} +``` + +Enable the site by running this command: + +```sh +ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/ +``` + +## Installing Nextcloud Itself + +We should have all the moving pieces in place now, so we can download and +install Nextcloud itself. First, download the latest Nextcloud 25 version and we will extract into `/var/www/` and ensure Nginx has the authority to use it. + +```sh +wget https://download.nextcloud.com/server/releases/latest-25.tar.bz2 +tar -xjf latest-25.tar.bz2 -C /var/www +chown -R www-data:www-data /var/www/nextcloud +chmod -R 755 /var/www/nextcloud +``` + +Start and enable php-fpm and reload nginx: + +```sh +systemctl enable php8.2-fpm --now +systemctl reload nginx +``` + +Now we need to head to Nextcloud\'s web interface. In a web browser, go to the domain we have installed Nextcloud on: + +- Choose an admin username and secure password. +- Leave Data folder at the default value unless it is incorrect. +- For Database user, enter the user you set for the SQL database. +- For Database password, enter the password you chose for the new user + in MariaDB. +- For Database name, enter: `nextcloud` +- Leave \"localhost\" as \"localhost\". +- Click Finish. + +Congratulations, you have set up your own Nextcloud instance. + +## What\'s Next? {#whatsnext} + +Now you may be wondering: What do I do now? Here are some suggestions: + +- Rice your Nextcloud instance by changing your themeing and + installing new themes and plugins in Settings in the Nextcloud Web + Interface. +- Install the Nextcloud Client on your personal computer and sync your + files to your instance. +- Install the Nextcloud App on your mobile device and sync your files + to your instance. +- Set up your email account on the Nextcloud Mail app on the web + interface to view and sync your email there (just like Gmail). +- Schedule events with Nextcloud Calender. +- Write notes in Markdown inside the Nextcloud Notes web and mobile + app. +- Set the Nextcloud Dashboard as your web browser\'s homepage (it is + pretty nice). + +In the event that anything goes wrong with the web interface of Nextcloud, Nextcloud has a commandline utility bundled with it called `occ`. You can use it with the following command: + +```sh +sudo -u www-data php /var/www/nextcloud/occ +``` + +You can make this an alias by putting it in your `~/.bashrc` file for ease of use with the following alias: + +```sh +alias occ="sudo -u www-data php /var/www/nextcloud/occ" +``` + +Enjoy your cloud services in freedom. + +## Contributor(s) + +- [Matthew \"Madness\" Evan](https://github.com/MattMadness) +- Edits by Luke diff --git a/content/nginx-tweaks.md b/content/nginx-tweaks.md new file mode 100644 index 0000000..8e85af5 --- /dev/null +++ b/content/nginx-tweaks.md @@ -0,0 +1,45 @@ +--- +title: "Nginx Tweaks" +date: 2022-06-16 +--- + +The point of this article is to show you how to do some commonly-desired tweaks +in Nginx while in the meantime helping you understand how it works. + +## Do not require `.html` in URLs + +If your website is using lots of `.html` files for pages, it\'s sort of +overkill to make people type that in for every page they are looking for. We +can remove that requirement with Nginx. + +Open your site\'s configuration file in `/etc/nginx/sites-enabled/` and within +the `server` block, there should be a `location` block that looks something +like this if you have followed [the guide here](/basic/nginx). + +```nginx +location / { + try_files $uri $uri/ =404 ; +} +``` + +What this means is that in the file location of `/`, i.e. anywhere and +everywhere in the root file system, We will look for the three things listed in +`try_files` in that order: + +1. `$uri`: a file that directly matches the content added after the domain. +2. `$uri/`: a *directory* that directly matches the content added after the + domain. +3. `=404`: if neither of those is found, we give a 404 error, which as you + probably know, signified \"Page not found.\" + +We will now change the content inside the `location` block to the below: + +```nginx +location / { + if ($request_uri ~ ^/(.*)\.html$) { return 302 /$1; } + try_files $uri $uri.html $uri/ =404 ; +} +``` + +`$1` here refers to the first content in the parentheses `()` in the preceeding +regular expression. diff --git a/content/openalias.md b/content/openalias.md new file mode 100644 index 0000000..49c73fe --- /dev/null +++ b/content/openalias.md @@ -0,0 +1,103 @@ +--- +title: "OpenAlias" +date: 2021-07-01 +tags: ["server"] +--- + +## The Problem + +Cryptocurrency can be unintuitive. After all, look at this annoying +Monero address of ours: + +- `84RXmrsE7ffCe1ADprxLMHRpmyhZuWYScDR4YghE8pFRFSyLtiZFYwD6EPijVzD3aZiEpg57MfHEr1pGJNPXyJgENMnWrSh` + +It breaks up pages and looks ugly. When you copy and paste it to send +money, you might be paranoid that you somehow added an extra character +in there. That\'s all around a bad user experience. + +### It would be nice\... + +It would be nice if we could just input someone\'s email address or +maybe a website and send Bitcoin or Monero to that instead. So instead +of that long jumble, it would be easier to just type in someone\'s +website or email and sending them money that way. + +## The Solution + +The [OpenAlias](https://openalias.org/) standards are just that. It uses +[DNS](/basic/dns) settings, which you know something about, to link a +website or an email address with a cryptocurrency address. It allows +someone to simply put `chad.thesiah.xyz` or `chad@thesiah.xyz` as a payment +recipient and that will direct to that long address above. + +The default Monero wallet and Bitcoin\'s Electrum are already compatible +with OpenAlias, as are a growing group of wallet software. + +## Let\'s do it. + +Open up your domain registar and open up your DNS settings for the +website you would like to add. + +Open the **TXT record** section. Now, create an entry with text like +that below: + +```txt +oa1:xmr recipient_address=84RXmrsE7ffCe1ADprxLMHRpmyhZuWYScDR4YghE8pFRFSyLtiZFYwD6EPijVzD3aZiEpg57MfHEr1pGJNPXyJgENMnWrSh; recipient_name=SiCh; +``` + +Obviously change the address to your desired address and you may also +give a proper name for yourself (this may be multiple words). Note that +the entry above is **all one line**. + +Now create a new TXT entry and input this text into the **TXT Value** +input box. Note here that I have create two entries: + +{{< img alt="openalias" src="/pix/openalias-01.png" link="/pix/openalias-01.png" >}} + +One entry\'s \"Host\" is left empty, this will allow people to send +Monero by merely typing `chad.thesiah.xyz`. + +The second entry has \"chad\" as the \"Host\"; this will allow people to +send money to `chad@thesiah.xyz`, i.e. this is how you allow people to +connect a Monero address with an email address. + +### Checking to see if it works\... + +Let\'s check to see if it works. In the Monero wallet, we can now type +in `chad.thesiah.xyz` as a recipient: + +{{< img alt="checking" src="/pix/openalias-02.png" link="/pix/openalias-02.png" >}} + +And once we press the \"Resolve\" button, it automatically turns into +that address we gave to the DNS! + +{{< img alt="It works!" src="/pix/openalias-03.png" link="/pix/openalias-03.png" >}} + +Now people can donate Monero to you without having to worry about QR +codes or copying-and-pasting super-long public addresses! + +### Now with Bitcoin! + +OpenAlias was originally developed for Monero, but since it\'s such a +good idea, Bitcoin wallets have implemented it as well, so let\'s add +some TXT entries for Bitcoin. The OpenAlias TXT records have the same +format, except for the **xmr** at the beginning is replaced with **btc** +and obviously we use a Bitcoin address instead of Monero. + +```txt +oa1:btc recipient_address=bc1q9f3tmkhnxj8gduytdktlcw8yrnx3g028nzzsc5; recipient_name=SiCh; +``` + +Add the TXT entries in and save: + +{{< img alt="bitcoin openalias entries" src="/pix/openalias-04.png" link="/pix/openalias-04.png" >}} + +And we can then check that it\'s working by trying to send money to +`chad.thesiah.xyz` in Electrum. See that it automatically appends the +address! + +{{< img alt="electrum resolves an openalias" src="/pix/openalias-05.png" link="/pix/openalias-05.png" >}} + +And that\'s it. Now users can easily send your website or email address +Bitcoin or Monero without having to worry about hard to read addresses +and QR codes. diff --git a/content/page-quality.md b/content/page-quality.md new file mode 100644 index 0000000..fc44e5e --- /dev/null +++ b/content/page-quality.md @@ -0,0 +1,210 @@ +--- +title: "Page Quality" +date: 2022-03-21 +tags: ["server"] +--- + +After you\'ve deployed your website, you may want to consider improving +its performance, accessibility, and search-engine optimization (SEO). +Doing so can help make your website more user-friendly and increase its +page rank in search results. Luckily, Google provides a [measurement +tool](https://web.dev/measure) to help you improve these aspects. Start by +entering your website\'s URL and click the _Run Audit_ button (it will +take 5-10 seconds to generate the report). + +Once the report has finished, you\'ll be greeted by a score for four +different categories: _Performance_, _Accessibility_, _Best Practices_, +and _SEO_. A lot of the tests listed are self-explanatory, and Google +provides you with articles to help you pass them. Below are some easy +ways to improve your scores, some specific to the nginx configuration +used in the [sich website tutorial.](/basic/nginx) + +## Performance + +### Serving static assets with an efficient cache policy + +Serving your files with an efficient cache policy will allow the user\'s +browser to cache files such as pictures and CSS so that the browser doesn\'t +need to fetch these files each time the page is visited. + +It\'s very easy to set this up in nginx. Just paste the following within the +server block of your website\'s configuration file: + +```nginx +# Media: images, icons, video, audio, HTC +location ~* \.(?:jpg|jpeg|gif|png|ico|svg|webp)$ { + expires 1M; + access_log off; + # max-age must be in seconds + add_header Cache-Control "max-age=2629746, public"; +} + +# CSS and Javascript +location ~* \.(?:css|js)$ { + expires 1y; + access_log off; + add_header Cache-Control "max-age=31556952, public"; +} +``` + +You can add more types of file extensions (mp3, mp4, ogg) as you see +fit. + +If you\'re changing your CSS files a lot, caching could keep repeat +users from getting the most up-to-date stylesheet. To combat this, you +can version your stylesheets like so: + +```html +<link rel="stylesheet" type="text/css" href="style.css?v=1.0.0" /> +``` + +Just increase the version number whenever you update your stylesheet, +and the browser will re-update its cache. + +### Enable text compression + +Another easy addition to your websites configuration file. Enabling text +compression is easy and will save bandwidth for users. Simply paste the +following within the server block of your website\'s configuration file: + +```nginx +gzip on; +gzip_min_length 1100; +gzip_buffers 4 32k; +gzip_types text/plain application/x-javascript text/xml text/css; +gzip_vary on; +``` + +After reloading nginx, you can test if compression is working by opening +your browsers developer tools and going to the network tab. Refresh your +website with the network tab, click on the item with your URL and look +at the response headers. You should see `Content-Encoding: gzip` as one +of the headers displayed. + +### Properly sizing images + +If you\'ve put images on your webpage, you\'ve most definitely gotten +this warning. To pass this audit, you\'ll need to scale your images down +using a tool like gimp or imagemagick to a size appropriate for your +website. It doesn\'t make much sense to serve a high-res image for +images that are rendered much smaller on a webpage. + +Once you\'ve scaled your image down, you can use a tool like `cwebp` to +convert your images into the .webp format, a format specifically created +for serving bandwidth concious images. + +First, you\'ll have to install the webp package: + +```sh +apt install webp +``` + +Now you can easily convert your images to webp (keep in mind that it\'s +much more effective to first size your images appropriately before +this). Using the below command, you can specify the quality of the photo +with the `q` option. I typically shoot for a quality in the range of +60-80, depending on the image and how large it will be displayed on the +webpage. + +```sh +cwebp -q 80 your-photo.png -o your-photo.webp +``` + +You can now check the difference in size of the images using `ls`. + +```sh +ls -lh your-photo* +``` + +After utilizing webp images, the audit typically goes away, but if you +didn\'t scale your image properly before hand, it may still linger. + +## Accessibility + +### Image elements do not have \[alt\] attributes + +It may seem silly to add `alt` attributes to images, but it helps screen +readers convey images to users and can help page rank as a result. The +`alt` attribute should simply describe the image being displayed. + +```html +<img src="img/cabin.webp" alt="A cabin nestled between pine trees" /> +``` + +## SEO + +### Document does not have a meta description + +Adding meta descriptions to your webpage allow for web-crawlers and bots +to easily determine what content your website contains. Just like on +other online platforms, you can give your webpage a long list of +keywords to help increase the chance someone stumbles upon your site +from a search engine. You don\'t need to add all of the below meta tags +to pass the audit, only add what\'s necessary. + +```html +<!--- Instructions for web scrapers ---> +<meta name="robots" content="index, follow" /> + +<meta name="description" content="your website description" /> +<meta name="keywords" content="your, keywords, here" /> +<meta name="author" content="your name" /> + +<!--- Facebook specific standard, but many websites use this so it has become almost standard to include ---> +<meta property="og:site_name" content="Site Name" /> +<meta name="twitter:domain" property="twitter:domain" content="example.org" /> +<meta name="og:title" property="og:title" content="Site Name" /> +<meta property="og:description" content="your website description" /> +<meta + name="twitter:description" + property="twitter:description" + content="your website description" +/> +<meta + name="og:image" + content="https://link-to-an-image-that-represents-your-site" +/> + +<!--- below is for twitter sharing previews +you can test this at cards-dev.twitter.com ---> +<meta + property="twitter:card" + content="https://link-to-an-image-that-represents-your-site" +/> +<meta + name="twitter:image:src" + property="twitter:image:src" + content="https://link-to-an-image-that-represents-your-site" +/> +<meta + name="twitter:image" + property="twitter:image" + content="https://link-to-an-image-that-represents-your-site" +/> +<meta + name="og:image:alt" + property="og:image:alt" + content="alt text for your image" +/> + +<meta property="og:url" content="example.org" /> +<meta property="og:type" content="website" /> + +<!--- If you have accounts on twitter or facebook that are relevant to your site ---> +<meta property="fb:admins" content="facebook group" /> +<meta + name="twitter:site" + property="twitter:site" + content="@yourTwitterHandle" +/> +<meta + name="twitter:creator" + property="twitter:creator" + content="@yourTwitterHandle" +/> +``` + +--- + +_Written by [Jacob.](https://mccor.xyz) Donate Monero +[here.](https://mccor.xyz)_ diff --git a/content/peertube.md b/content/peertube.md new file mode 100644 index 0000000..f666f9f --- /dev/null +++ b/content/peertube.md @@ -0,0 +1,473 @@ +--- +title: "PeerTube" +date: 2021-07-31 +icon: "peertube.svg" +tags: ["service", "activity-pub"] +short_desc: "Your own self-hosted video-site also compatible with Activity Pub." +--- + +PeerTube is a self-hosted and (optionally) federated video sharing +platform that saves bandwith on videos the more people watch. PeerTube +instances can follow each other to share videos and grow the federated +network, but you can always keep your instance to yourself if you choose +to. + +## Note on Bandwidth + +Video sharing is the most bandwidth intensive thing on the internet! If +you plan on just having a small personal site with a few viewers and +friends, that won\'t be a big concern, but most VPS providers like Vultr +have caps on how much bandwidth can be used within a month without being +throttled. This level is far beyond what most sites need, but it might +be an issue with a video site! + +So if you plan on having a big video-sharing PeerTube site, it\'s a good +idea to host it with a provider that offers infinite bandwidth. I +strongly recommend getting a separate VPS with +[Frantech/BuyVM](https://my.frantech.ca/aff.php?aff=3886). They have +unmetered bandwidth, extremely cheap block storage for hosting many, +many videos and they even have a good record of being censorship +resistant. + +## Prerequisites + +**Most** of PeerTube\'s dependencies can be installed with this command: + +```sh +apt update +apt install -y curl sudo unzip vim ffmpeg postgresql postgresql-contrib g++ make redis-server git cron wget certbot nginx ffmpeg postgresql postgresql-contrib openssl g++ make redis-server git cron wget +apt install python3-dev python3-pip python-is-python3 +python --version # Should be >= 3.8 +ffmpeg -version # Should be >= 4.1 +g++ -v # Should be >= 5.x +redis-server --version # Should be >= 6.x +``` + +It\'s also important to start all associated daemons: + +```sh +systemctl start postgresql redis +``` + +PeerTube also requires **NodeJS 14** and **yarn** which cannot be +installed from the Debian repositories. This means they have to be +installed from separate, external repos: + +```sh +curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh +bash nodesource_setup.sh +apt install -y nodejs +node -v # Should be 20.x or 22.x +``` + +Now we create a PeerTube user to run and handle PeerTube with the proper +permissions: + +```sh +useradd -m -d /var/www/peertube -s /bin/bash -p peertube peertube +passwd peertube +ls -ld /var/www/peertube # Should be drwxr-xr-x +``` + +## Database + +PeerTube requires a PostgreSQL database to function. To create it, first +make a new Postgres user named PeerTube: + +```bash +su -l postgres +createuser -P peertube +createdb -O peertube -E UTF8 -T template0 peertube_prod +psql -c "CREATE EXTENSION pg_trgm;" peertube_prod +psql -c "CREATE EXTENSION unaccent;" peertube_prod +exit +``` + +Be sure to **make note of your Postgres user password,** as it will be +needed later when setting up PeerTube. + +## Installation + +Using `su -l`, we will become the PeerTube user to create the required +directories and download and install PeerTube itself with the proper +permissions. First, we create the required directories. + +```sh +su -l peertube +mkdir config storage versions +chmod 750 config/ +``` + +### Downloading PeerTube + +Still as the PeerTube user, we can now check for the most recent +PeerTube versions number, download and install it in the newly created +`versiond` directory. + +```bash +VERSION=$(curl -s https://api.github.com/repos/chocobozzz/peertube/releases/latest | grep tag_name | cut -d '"' -f 4) && echo "Latest Peertube version is $VERSION" +cd /var/www/peertube/versions +wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip" +unzip -q peertube-${VERSION}.zip && rm peertube-${VERSION}.zip +``` + +### Installation via Yarn + +The downloaded release can then be symbolically linked to +`/var/www/peertube/peertube-latest` and **yarn** is used to install +PeerTube: + +```sh +cd /var/www/peertube +ln -s versions/peertube-${VERSION} ./peertube-latest +cd ./peertube-latest +yarn install --production --pure-lockfile +``` + +## Configuration + +PeerTube's default config file can be copied over to +`/var/www/peertube/config/production.yaml` so it can actually be used: + +Note that we are still running these as the PeerTube user (having run +`su -l peertube`). + +```sh +cd /var/www/peertube +cp peertube-latest/config/default.yaml config/default.yaml +cp peertube-latest/config/production.yaml.example config/production.yaml +``` + +Now the `production.yaml` file must be edited in the following ways: + +First, generate a secret key by `openssl rand -hex 32`: + +```yaml +secrets: + # Generate one using `openssl rand -hex 32` + peertube: "5e55258877f5d259cb1b5e5562dcb0eded3a2c3373d9fafac65ed765fbb1936c" +``` + +Add the hostname: + +```yaml +webserver: + https: true + hostname: "peertube.thesiah.xyz" + port: 443 +``` + +Then, the database: + +```yaml +database: + hostname: "localhost" + port: 5432 + ssl: false + suffix: "_prod" + username: "peertube" + password: "your_database_password" + pool: + max: 5 +``` + +An email to generate the admin user: + +```yaml +admin: + # Used to generate the root user at first startup + # And to receive emails from the contact form + email: "peertube@thesiah.xyz" +``` + +And **optionally,** email server information: + +```yaml +smtp: + # smtp or sendmail + transport: smtp + # Path to sendmail command. Required if you use sendmail transport + sendmail: null + hostname: mail.example.org + port: 465 # If you use StartTLS: 587 + username: your_email_username + password: your_email_password + tls: true # If you use StartTLS: false + disable_starttls: false + ca_file: null # Used for self signed certificates + from_address: "admin@example.org" +``` + +At this point, we have done all we need to do as the PeerTube user. Run +`exit` or press <kbd>Ctrl-d</kbd> to log out and return to the root prompt where +we will configure Nginx and other system settings. + +```sh +exit +``` + +## Nginx + +PeerTube includes an Nginx configuration that can be copied over to +`/etc/nginx/sites-available:` + +```sh +cp /var/www/peertube/peertube-latest/support/nginx/peertube /etc/nginx/sites-available/peertube +``` + +Because the PeerTube config is so long, it\'s recommended to use `sed` +to modify the contents of the file, replacing `${WEBSERVER_HOST}` with +your hostname, and `$(PEERTUBE_HOST)` with your localhost and port, +which by default should be `127.0.0.1:9000`: + +```sh +sed -i 's/${WEBSERVER_HOST}/videos.thesiah.xyz/g' /etc/nginx/sites-available/peertube +sed -i 's/${PEERTUBE_HOST}/127.0.0.1:9000/g' /etc/nginx/sites-available/peertube +``` + +Once you\'re happy with the Nginx config file, link it to +`sites-enabled` to activate it: + +```sh +ln -s /etc/nginx/sites-available/peertube /etc/nginx/sites-enabled/peertube +``` + +## Certbot + +First, we will want a Certbot SSL certificate to encrypt connections to +our PeerTube instance. Just run the following: + +```sh +systemctl stop nginx +certbot certonly --standalone -d videos.thesiah.xyz +systemctl restart nginx +``` + +## Running PeerTube + +A config file for a systemd daemon is included in PeerTube and can be +setup and started like so: + +```sh +cp /var/www/peertube/peertube-latest/support/systemd/peertube.service /etc/systemd/system/ +systemctl daemon-reload +systemctl enable --now peertube +systemctl start peertube +journalctl -feu peertube +``` + +PeerTube will take a minute or so to start, but after it does, you can check +its status with `systemctl status peertube` and at this point, your +PeerTube site should be live! + +## Using PeerTube + +To get the automatically generated admin password, run: + +```sh +cat /var/www/peertube/storage/logs/peertube.log | grep password +``` + +To set a password for your admin user, run: + +```sh +cd /var/www/peertube/peertube-latest +NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u root +``` + +Login to your PeerTube instance using the admin email specified in your +`production.yaml` file and the admin password you just set. + +{{< img alt="PeerTube login" src="/pix/peertube-login.jpg" >}} + +Once logged in, it\'s recommended to create a separate user without +admin privileges for uploading videos to PeerTube. This can be done +easily from the users tab in the administration section. + +Enjoy your PeerTube instance! + +--- + +## Updating PeerTube + +PeerTube is constantly adding new features, so it\'s a good idea to +[check for new +updates](https://github.com/Chocobozzz/PeerTube/blob/develop/CHANGELOG.md) +and add them if you wish. Just in the past year, they have added +livestreaming and more. + +### PeerTube instance + +Updating is fairly easy now since an `upgrade.sh` script has been added. +Just run: + +```sh +cd /var/www/peertube/peertube-latest/scripts && sudo -H -u peertube ./upgrade.sh +sudo systemctl restart peertube # Or use your OS command to restart PeerTube if you don't use systemd +``` + +### Update PeerTube configuration + +Check for configuration changes, and report them in your `config/production.yaml` file: + +```sh +cd /var/www/peertube/versions +diff -u "$(ls -t | head -2 | tail -1)/config/production.yaml.example" "$(ls -t | head -1)/config/production.yaml.example" +``` + +### Update nginx configuration + +Check changes in nginx configuration: + +```sh +cd /var/www/peertube/versions +diff -u "$(ls -t | head -2 | tail -1)/support/nginx/peertube" "$(ls -t | head -1)/support/nginx/peertube" +``` + +### Update systemd service + +Check changes in systemd configuration: + +```sh +cd /var/www/peertube/versions +diff -u "$(ls -t | head -2 | tail -1)/support/systemd/peertube.service" "$(ls -t | head -1)/support/systemd/peertube.service" +``` + +### Restart PeerTube + +If you changed your nginx configuration: + +```sh +sudo systemctl reload nginx +``` + +If you changed your systemd configuration: + +```sh +sudo systemctl daemon-reload +``` + +Restart PeerTube and check the logs: + +```sh +sudo systemctl restart peertube +sudo journalctl -fu peertube +``` + +Although check the +[changelog](https://github.com/Chocobozzz/PeerTube/blob/develop/CHANGELOG.md) +to see if there are additional manual requirements for particular +updates. + +## Things went wrong? + +Change peertube-latest destination to the previous version and restore your SQL backup: + +```sh +OLD_VERSION="v0.42.42" && SQL_BACKUP_PATH="backup/sql-peertube_prod-2018-01-19T10:18+01:00.bak" && \ + cd /var/www/peertube && sudo -u peertube unlink ./peertube-latest && \ + sudo -u peertube ln -s "versions/peertube-$OLD_VERSION" peertube-latest && \ + sudo -u postgres pg_restore -c -C -d postgres "$SQL_BACKUP_PATH" && \ + sudo systemctl restart peertube +``` + +## Remote PeerTube CLI + +`peertube-cli` is a tool that communicates with a PeerTube instance +using its REST API. It can be launched from a remote server/computer +to easily upload videos, manage plugins, redundancies etc. + +### Installation + +Ensure you have node installed on your system: + +```sh +node --version # Should be >= 16.x +``` + +Then install the CLI: + +```sh +sudo npm install -g @peertube/peertube-cli +``` + +### CLI wrapper + +The wrapper provides a convenient interface to the following sub-commands. + +The wrapper can keep track of instances you have an account on. We limit +to one account per instance for now. + +```sh +peertube-cli auth add -u 'PEERTUBE_URL' -U 'PEERTUBE_USER' --password 'PEERTUBE_PASSWORD' +peertube-cli auth list +┌──────────────────────────────┬──────────────────────────────┐ +│ instance │ login │ +├──────────────────────────────┼──────────────────────────────┤ +│ 'PEERTUBE_URL' │ 'PEERTUBE_USER' │ +└──────────────────────────────┴──────────────────────────────┘ +``` + +### peertube-cli upload + +You can use this script to upload videos directly from the CLI. + +Videos will be publicly available after transcoding +(you can see them before that in your account on the web interface). + +```sh +cd ${CLONE} +peertube-cli upload --help +peertube-cli upload "videoFile" +peertube-cli plugins list +``` + +peertube-cli plugins + +Install/update/uninstall or list local or NPM PeerTube plugins: + +```sh +cd ${CLONE} +peertube-cli plugins --help +peertube-cli plugins list --help +peertube-cli plugins install --help +peertube-cli plugins update --help +peertube-cli plugins uninstall --help + +peertube-cli plugins install --path /my/plugin/path +peertube-cli plugins install --npm-name peertube-theme-example +``` + +### peertube-cli redundancy + +Manage (list/add/remove) video redundancies: + +To list your videos that are duplicated by remote instances: + +```sh +peertube-cli redundancy list-remote-redundancies +``` + +To list remote videos that your instance duplicated: + +```sh +peertube-cli redundancy list-my-redundancies +``` + +To duplicate a specific video in your redundancy system: + +```sh +peertube-cli redundancy add --video 823 +``` + +To remove a video redundancy: + +```sh +peertube-cli redundancy remove --video 823 +``` + +--- + +_Written by [TheSiahxyz.](https://thesiah.xyz) Donate Monero +[here](https://thesiah.xyz/donate.html) +[\[QR\]](https://thesiah.xyz/images/monero.jpg)_ diff --git a/content/pleroma.md b/content/pleroma.md new file mode 100644 index 0000000..9714e3b --- /dev/null +++ b/content/pleroma.md @@ -0,0 +1,186 @@ +--- +title: "Pleroma" +date: 2021-07-01 +icon: 'pleroma.svg' +tags: ['service','activity-pub'] +short_desc: 'A federated Twitter-like microblogging system.' +--- +Hopefully by now you won\'t have to be sold on the invasive practices +that social media companies conduct. Websites such as Facebook and +Twitter aquire so much data on users that they often know more about you +than you know about yourself. The simple solution to this is to not use +social media. However, that just isn\'t an option for most people. So +the next best thing is to setup a self-hosted and federalised social +media site so that you have full control over your data. I\'ve +previously made [a video showing all the steps in depth if you want to +check it out.](https://www.youtube.com/watch?v=l7mVsLSsotU) If you run +into any issues I suggest you look at the video. + +You\'ll need a server or VPS. Nearly any Operating system is supported +but for this tutorial I\'m gonna presume you\'re using a Debian-based +OS. You\'ll also need a domain name pointing to your server\'s IP +address [which is explained in this tutorial.](/basic/dns) + +## Installation + +### Setting Up and Configuring + +First things first you\'ll need to make sure that you\'ve hardened you +SSH so that password authentication is disabled and you\'ll also want to +setup Fail2Ban. There\'s a great tutorial on how to do this [which can +be read here.](/sshkeys) + +Next we\'ll install the required packages: + +```sh +apt install -y curl unzip libncurses5 postgresql postgresql-contrib nginx certbot libmagic-dev +``` + +You can manually configure postgreSQL to suit your system better. [Check +out the documentation +here](https://docs-develop.pleroma.social/backend/configuration/postgresql/) +and then run the below command: + +```sh +systemctl restart postgresql +``` + +### Installing the Pleroma App + +#### First as the root user + +Pleroma is not in the Debian app repositories, so we will install it +manually. First create the Pleroma user by running the below command: + +```sh +useradd -m -s /bin/bash -d /opt/pleroma pleroma +``` + +Then, still as root, we will create the required directories and give +the Pleroma user ownership of them. + +```sh +mkdir -p /var/lib/pleroma/uploads +chown -R pleroma /var/lib/pleroma +mkdir -p /var/lib/pleroma/static +chown -R pleroma /var/lib/pleroma +mkdir -p /etc/pleroma +chown -R pleroma /etc/pleroma +``` + +#### Now, as the new Pleroma user + +Now run `su -l pleroma` to login as the Pleroma user. Now use the `curl` +command below to download the Pleroma software and unzip it. + +```sh +curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=amd64' -o /tmp/pleroma.zip +unzip /tmp/pleroma.zip -d /tmp/ +``` + +Note that we are downloading the **amd64** version here. If you know you +have a different CPU architecture, replace that with whatever your +architecture is. + +```sh +mv /tmp/release/* /opt/pleroma +rmdir /tmp/release +rm /tmp/pleroma.zip +./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql +``` + +We need to briefly return to the root user so we can run the following +command (via the postgres user) to set up the database. Type <kbd>ctrl-d</kbd> or +run `exit` to return to the root user, then run: + +```sh +su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql" +``` + +Then return to the pleroma user with `su -l pleroma` and we will test to +see that Pleroma can run: + +```sh +./bin/pleroma_ctl migrate +./bin/pleroma daemon +``` + +That will initialize Pleroma. It might take as long as a minute to get +started, so wait a bit, then run the following: + +```sh +curl http://localhost:4000/api/v1/instance +``` + +If everything is working, this command will give you a long line of +messy output. If it is not, you will get a connection error message. +Once it is working successfully, stop the Pleroma daemon and we will +interface Pleroma with the web server. + +```sh +./bin/pleroma stop +``` + +### Setup and Configure Nginx + +Return again to the root user. Let\'s copy Pleroma\'s Nginx +configuration file from the template given in the installation and +enable it: + +```sh +cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf +ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf +``` + +Edit the `etc/nginx/sites-available/pleroma.conf` file and replace +**example.tld** with your domain name. + +We now have to get a SSL certificate to enable encryption, since we have +a model configuration that already includes SSL information, just check +the brief [the standalone certificate page](/standalone) to get the +needed certificate. Once you\'ve got your cert setup, copy over the +Nginx configuration with the below command: + +Once everything, including your Cerbot certificate is ready, simply +reload Nginx with this command: + +```sh +systemctl reload nginx +``` + +### Setting up the service + +Pleroma itself runs on a SystemD service similar to other things running +on your server like Nginx. To start the service up run the below +commands: + +```sh +cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service +systemctl start pleroma +systemctl enable pleroma +``` + +If everything worked then when you go to your domain in the web browser +you should see a bare-bones Pleroma instance. + +### Creating an Admin User + +You\'ll be able to create new accounts on the Pleroma instance in the +login section on the website but the easiest way to setup an admin +account is with the CLI. Simply run the below command replaced with your +username: + +```sh +su -l pleroma +./bin/pleroma_ctl user new username username@example.org --admin +``` + +If you run into any issues then [feel free to checkout the +documentation](https://docs-develop.pleroma.social/backend/installation/otp_en/) +or send me an email or message. My details are below. + +- [biasedriot.co](https://biasedriot.co) +- [youtube](https://www.youtube.com/channel/UCehh50T6qtDpt_kEUF33GJw) +- Bitcoin: `1Dmn9jEtWAhdLk1HHWkUVNeDdAaBCwNajm`{.crypto} +- Monero: + `84Y4FZiTbLeR5qc1fBrBhB1yq5agKtEdoixq2w1ysXJv486MiBCz3czGT15bqeXDPpdLoNyF93inxY3BCk6g8mrDMNKoArS` diff --git a/content/prosody.md b/content/prosody.md new file mode 100644 index 0000000..df18ad3 --- /dev/null +++ b/content/prosody.md @@ -0,0 +1,272 @@ +--- +title: "Prosody" +date: 2022-04-03 +icon: 'prosody.svg' +tags: ['service'] +short_desc: 'A minimalist XMPP chat server.' +--- + +XMPP is a fantastically simple protocol that's usually used as a messenger. It's highly extensible, better than IRC, lighter and more decentralized than Matrix, and normie social media like Telegram can't hold a candle to it. + +XMPP is so decentralized and extensible that there are many [*different*](/ejabberd) XMPP servers. Here, let's set up a [Prosody](https://prosody.im/) XMPP server. + +## Installation + +To install Prosody, first add the official Prosody repositories for Debian: + +```sh +# Install extrepo if you already haven't +apt install extrepo +extrepo enable prosody +apt update +``` +Then, install Prosody: + +```sh +apt install prosody +``` + +## Configuration + +The Prosody configuration file is in `/etc/prosody/prosody.cfg.lua`. To set it all up, we will be changing several things. + +### Setting Admins + +Let's go ahead and set who our admin(s) will be. Find the line that says `admins = { }` and to this we can specify one or more server admins. + +```cfg +# To add one admin: +admins = { "chad@example.org" } + +# We can add more than one by separating them by commas. (This file is written in Lua.) +admins = { "chad@example.org", "chadmin@example.org" } +``` + +Note that we have not created these accounts yet, we will do this [below](#user). + +### Set the Server URL + +Find the line `VirtualHost "localhost"` and replace `localhost` with your domain. In our case, we will have `VirtualHost "example.org"` + +### Multi-User Chats + +Most people will probably want the ability to have chats with more than two users. This is easily enough to enable. In the config file, add the following: + +```cfg +Component "chat.example.org" "muc" + modules_enabled = { "muc_mam" } + restrict_room_creation = "admin" +``` + +On the first line, you must have a separate subdomain for your multi-user chats. I use the `chat.` subdomain, but some use `muc.`. Anything is possible. + +The second line is important because it prevents non-admins from creating and squatting rooms on your server. The only situation where you might not want that is if you indend to open a general public chat system for people you don't know. + +Read more about the `muc` plugin on the Prosody documentation page [here](https://prosody.im/doc/modules/mod_muc). + +### Enabling Chat Histories + +By default, Prosody will send out messages received only to the first available clients. +That means that if you have your desktop client turned off and your cell phone receives a message, +it will *not* be available to the desktop client when you start it. + +While this may be preferred in some cases, +enable the `mam` module (Message Archive Management) to have the server hold on messages and sync them to all clients. + +Within the `modules_enabled` block, you can uncomment the `mam` line to enable it. +You can see other settings for this module [here](https://prosody.im/doc/modules/mod_mam) +like, for example, how long a server should hold on to message histories for synching. + +Note also that Prosody comes with the `carbons` activated module by default, which is related. +This will send received messages to *all* active clients (your phone and desktop), +although it will not save messages like MAM for clients not online or to be added later. + +### File sharing + +With this we can bring XMPP to the level of other popular instant messaging applications like Matrix and whatsapp. +It is extremely easy to setup. +This part is optional, but it can make XMPP more normie-friendly if you plan on moving family members and friends over to XMPP. + +Add the following line to your prosody config file to enable file uploads: + +```cfg +Component "{{<hl>}}uploads.example.org{{</hl>}}" "http_file_share" +``` + +As you will notice, you need another subdomain for this. We will add an ssl certficate for this later. + +### Proxy Support + +This helps with file transfers for devices behind a NAT, and unless you are using XMPP in a LAN, you **probably need this.** +Enable the proxy by adding the following line to the config: + +```cfg +Component "{{<hl>}}proxy.example.org{{</hl>}}" "proxy65" +``` + +As you can see, another subdomain is needed. We will add ssl certificates for this later. + +At this point, file sharing is now setup and ready to be used. Although there are some concerns that should be addressed. + +A big concern with file sharing is large files, seeing as all files shared over XMPP will be stored on your server. This can become a problem when many (and large) files are being shared. We can put a cap on large files by adding the following line to our config: + +```cfg +http_file_share_size_limit = 20971520 +``` + +This puts a 20MB cap on all files being shared. The value is specified in bytes. You can also specify after how long files should be deleted by adding the following line: + +```cfg +http_file_share_expire_after = 60 * 60 * 24 * 7 +``` + +The value is specified in seconds. The above line will make prosody delete files after a week. + +### Database Setup + +Prosody includes the `internal` and `sql` storage backends by default. +If you wish to run Prosody with PostgreSQL, begin by installing the PostgreSQL: + +```sh +apt install postgresql lua-dbi-postgresql +``` + +Then start the daemon: + +```sh +systemctl restart postgresql +``` + +Now create a user named `prosody` to manage your database: + +```sh +su -c "createuser --pwprompt prosody" postgres +``` + +And finally, create the actual database: + +```sh +su -c "psql -c 'CREATE DATABASE prosody OWNER prosody;'" postgres +``` + +Finally, in `/etc/prosody/prosody.cfg.lua`, edit the following lines: + +```cfg +storage = "sql" + +sql = { + driver = "PostgreSQL", + database = "{{<hl>}}prosody{{</hl>}}", + username = "{{<hl>}}prosody{{</hl>}}", + password = "{{<hl>}}password{{</hl>}}", + host = "localhost" +} +``` + +### Voice and Video Calling + +Prosody supports XMPP voice and video calls through an external TURN and STUN server. + +First, follow the guide on installing and setting up [coturn,](/coturn) setting **only a shared secret** for authentication. + +Then, uncomment the `turn_external` module in the modules section in `prosody.cfg.lua`. + +```cfg +"turn_external"; +``` + +Finally, specify the host and credentials lower in the config: + +```cfg +-- Specify the address of the TURN service (you may use the same domain as XMPP) +turn_external_host = "{{<hl>}}turn.example.org{{</hl>}}" + +-- This secret must be set to the same value in both Prosody and the TURN server +turn_external_secret = "{{<hl>}}your shared secret{{</hl>}}" +``` + +### Other things to check + +Check the config file for other settings you might want to change. For example, if you want to run a general public XMPP server, you can allow anyone to create an account by changing `allow_registration` to `true`. + +Another thing you can do is enable the `csi_simple` module, which will add some optimizations for mobile devices. + +Another thing worth noting is the `archive_expires_after = "1w"` line. This specifies after how long message archives will be deleted. + +Also the `smacks` module helps a lot with slow internet connections. + +## Certificates + +Obviously, we want to have client-to-server and server-to-server encryption. Nowadays, use can use Certbot to generate certificates and use a convenient command below `prosodyctl` to import them. + +**If you have multi-user chat enabled, be sure to get a certificate for that subdomain as well.** Include the `--nginx` option assuming you have an Nginx server running. + +```sh +certbot -d {{<hl>}}chat.example.org{{</hl>}} --nginx +``` + +**If you have file sharing enabled, be sure to get a certificate for those subdomains as well.** + +```sh +certbot -d {{<hl>}}uploads.example.org{{</hl>}} --nginx +certbot -d {{<hl>}}proxy.example.org{{</hl>}} --nginx +``` + +Once you have the certificates for encryption, run the following to import them into Prosody. + +```sh +prosodyctl --root cert import /etc/letsencrypt/live/ +``` + +Note that you might get an error that a certificate has not been found if your `muc` subdomain and your main domain share a certificate. It should still work, this is just notifying you that no specific certificate for the subdomain. + +**Note:** The above command will need to be rerun when certificates are renewed. You may want to create a [cronjob](/cron) to have this done automatically. + +## Creating users/admins manually {#user} + +Let's manually create the admin user we prepared for above. Note that you can indeed do this in your XMPP client if you have not disabled registration, but this is how it is done on the command line: + +```sh +prosodyctl adduser {{<hl>}}chad@example.org{{</hl>}} +``` + +This will prompt you to create a password as well. + +## Make changes active + +With any system service, use `systemctl reload` or `systemctl restart` to make the new settings active: + +```sh +systemctl restart prosody +``` + +## Using your Server! + +Once your server is set up, you just need an XMPP client to use your new and secure chat system. + +- GNU/Linux: [Dino](https://dino.im/) or [Gajim](https://gajim.org/) +- Windows: [Gajim](https://gajim.org/) also runs on Windows. +- Android: [Conversations.im](https://conversations.im/) or + [snikket](https://snikket.org/) +- Mac/iOS: [Monal IM](https://monal-im.org/) or + [Siskin](https://siskin.im/) for iOS alone +- command-line (GNU/Linux, MacOS, Windows): + [Profanity](https://profanity-im.github.io/) +- [See a more complete list kept by + XMPP](https://xmpp.org/software/clients.html) + +Install whichever of these clients you want on your computer or phone and you can log into your new XMPP server with the account you made. Note that if you enabled public registration, anyone can create an account on your server through one of these clients. + +### Account addresses + +XMPP account addresses look just like email addresses: `username@example.org`. You can message any account on any XMPP server on the internet with that format. + +### Note on MUCs (multi-user chats) + +Remember that MUCs are kept on a separate subdomain that we created and should've gotten a certificate for above, for example, `chat.example.org`. Chatrooms are created and referred to in the following format: `#chatroomname@chat.example.org`. + +### Note on firewalls and opening ports + +If you use a firewall, you should open ports 5222 and 5281. The first one is needed for clients to be able to connect to your server. The second is only necessary if you are using the `http_file_share` module for file sharing, as 5281 is the port for serving content over HTTPS. + +A complete list of ports used by Prosody can be found [here](https://prosody.im/doc/ports). diff --git a/content/radicale.md b/content/radicale.md new file mode 100644 index 0000000..01427cb --- /dev/null +++ b/content/radicale.md @@ -0,0 +1,111 @@ +--- +title: "Radicale" +date: 2021-10-07 +pix: "radicale.svg" +icon: "radicale.svg" +tags: ["service"] +short_desc: "A private calendar, contact and to-do list system." +--- + +Radicale is an open source calDAV server. CalDAV is a widely supported +internet standard for calendars, todo-lists and contacts. Hosting your +own calDAV server allows sharing calendars between mutliple devices. + +More information can be found on the projects offical website: +[radicale.org](https://radicale.org/v3.html). + +## Installing Radicale + +Firstly, we have to install radicale on our system, luckily for us +radicale is packaged for the most used distros. + +```sh +apt install radicale apache2-utils +``` + +Next we need to configure Radicale. We configure radicale to be +accessible from other machines, how Radicale handles users and where the +files should be stored. Open /etc/radicale/config with your favourite +editor and add this configuration. + +```systemd +[server] +# Bind all addresses +hosts = 0.0.0.0:5232, [::]:5232 + +[auth] +type = htpasswd +htpasswd_filename = /etc/radicale/users +htpasswd_encryption = bcrypt + +[storage] +filesystem_folder = /var/lib/radicale/collections +``` + +As you can see under \[auth\] we use htpasswd to manage the users. +Execute the following command to add a new user to Radicale. + +```sh +htpasswd -B -c /etc/radicale/users username +``` + +To create additional users, htpasswd is used again but without the additional modifier. + +```sh +htpasswd -B /etc/radicale/users username2 +``` + +As Radicale stands now it is fully functional and after starting it by +executing its binary, can be accessed under example.org:5232. But there +are two additional things we can do to make using and managing Radicale +way easier. + +### Setting up a Nginx reverse proxy + +Because the URL of your Radicale server is an URL you will have to +remember and enter it on any device you want to use your calendar on it +is advised to set up a reverse proxy. + +```nginx +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name cal.example.org; + location / { + proxy_pass http://localhost:5232/; # The / is important! + } + # You can also leave these two lines out and use certbot + ssl_certificate /etc/ssl/nginx/cal.example.com/fullchain.pem; + ssl_certificate_key /etc/ssl/nginx/cal.example.com/privkey.pem; +} +``` + +### Run as a service + +Running Radicale as a service makes managing it much easier. Add this +config to /etc/systemd/system/radicale.service. + +```systemd +[Unit] +Description=A simple CalDAV (calendar) and CardDAV (contact) server + +[Service] +ExecStart=/usr/bin/env python3 -m radicale +Restart=on-failure + +[Install] +WantedBy=default.target +``` + +After creating the config load, start and enable the service with the +following commands. + +```sh +systemctl daemon-reload +systemctl enable --now radicale +``` + +## Contribution + +Author: Jocomol -- [jocomol.ch](https://jocomol.ch) \-- XMR: +`41kLv68Nk4N3zvTRFYtHZfRRFMgXkxK2FcXDeCSa4yNwBGTBa1WQ8HtXL8cCAcoZ2iSLBCS6HQqdpRSf56ecMBgWTkn2ARt`{.crypto} diff --git a/content/rainloop.md b/content/rainloop.md new file mode 100644 index 0000000..2018482 --- /dev/null +++ b/content/rainloop.md @@ -0,0 +1,119 @@ +--- +title: "Rainloop" +tags: ['service'] +icon: 'rainloop.png' +short_desc: 'A graphical website for accessing a mail server.' +date: 2022-06-25 +--- + + +[Rainloop](https://www.rainloop.net/) +is a webmail client, a program that allows you to access your email +online like Gmail. It is useful to be able to access you email from a +web browser because it allows you to easily access your email from any +device with a web browser without any additional setup. + +If you set up +[Nextcloud](/nextcloud) +then you do not need to install Rainloop because Nextcloud comes with a +webmail client. However, if all you want is a webmail client and you do +not need all of the extra things that Nextcloud provides, Rainloop would +be the better choice out of the two since it is less bloated and simpler +to install. + +## Instructions + +First we will install the required packages for Rainloop with the +following command: + +```sh +apt-get install php php-common php-curl php-xml php-fpm php-json php-dev php-mysql unzip -y +``` + +Then we will download the community version of Rainloop, unzip it into +an appropriate directory and fix all of the file permissions: + +```sh +curl -L "https://www.rainloop.net/repository/webmail/rainloop-latest.zip" -o "rainloop.zip" +unzip rainloop.zip -d /var/www/mail +chown -R www-data: /var/www/mail +``` + +We have installed Rainloop itself, but now we need Nginx to serve the +client. We do that by adding the following text into the file +`/etc/nginx/sites-available/mail` (you can replace the bold text with +whatever is appropriate for your server). + +```nginx +server { + + listen 80; + listen [::]:80; + + server_name mail.example.org ; + root /var/www/mail; + + index index.php; + + access_log /var/log/nginx/rainloop_access.log; + error_log /var/log/nginx/rainloop_error.log; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_index index.php; + fastcgi_split_path_info ^(.+\.php)(.*)$; + fastcgi_keep_conn on; + fastcgi_pass unix:/var/run/php/php-fpm.sock; + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + location ~ /\.ht { + deny all; + } + + location ^~ /data { + deny all; + } +} +``` + +Then enable the site by linking it to the sites-enabled directory: + +```sh +ln -s /etc/nginx/sites-available/mail /etc/nginx/sites-enabled/ +``` + +Reload nginx: + +```sh +systemctl reload nginx +``` + +Finally get certifications if you are using a new subdomain: + +```sh +certbot --nginx +``` + +After that go to `mail.example.org/?admin` and login with the default +username and password: admin, 12345. Now you are in the admin panel and +the first thing you do should be to change the adminsitrator password by +looking in the security tab on the left. + +{{< img alt="rainloop" src="/pix/rainloop-1.png" >}} + +After securing the admin account you can go to domains and add your own +email address. + +{{< img alt="rainloop" src="/pix/rainloop-2.png" >}} + +Finally, go to `mail.example.org` and login with your email address and +password. + +## Contribution + +[Deniz Telci](https://deniz.telci.org/) - XMR: +`4AcKbpTUc3QX2zHYdh9HZwJAQyexdybFhF1WhXTFhxAcV9jgzB6kroqGZDgeW3rQqXEMYJioYo61kaLBqstwecty9Bjbr4v` diff --git a/content/rss-bridge.md b/content/rss-bridge.md new file mode 100644 index 0000000..8afc4bd --- /dev/null +++ b/content/rss-bridge.md @@ -0,0 +1,115 @@ +--- +title: "RSS Bridge" +date: 2021-07-05 +tags: ["service"] +icon: "rss.svg" +short_desc: "Creates RSS feeds for normie sites like Facebook." +--- + +RSS Bridge is a useful utility you can use to help you avoid the big +tech sites, like Facebook and Twitter, which instead of the feed you +usually would see, will be a based and minimalist RSS feed. + +You\'ll need a server or VPS. Nearly any Operating system is supported +but for this tutorial I\'m gonna presume you\'re using a Debian-based +OS. You\'ll also need a domain name pointing to your server\'s IP +address [which is explained in this tutorial.](/basic/dns) + +## Installation + +### Setting Up and Configuring + +First things first you\'ll need to make sure that you\'ve hardened you +SSH so that password authentication is disabled and you\'ll also want to +setup Fail2Ban. There\'s a great tutorial on how to do this [which can be read here.](/sshkeys) + +Next we\'ll install the required packages: + +```sh +apt install -y curl unzip nginx certbot php-fpm php-mysql php-cli php-mbstring php-curl php-xml php-sqlite3 php-json +``` + +We now have to create the website configuration file. Create/open the a +file below: + +```sh +nano /etc/nginx/sites-available/rss-bridge +``` + +And add the following content: + +```nginx +server { + root /var/www/rss-bridge; + index index.php index.html index.htm index.nginx-debian.html; + server_name rss-bridge.example.org; + + location / { + try_files $uri $uri/ =404; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + fastcgi_pass unix:/var/run/php/php-fpm.sock; + } + + location ~ /\.ht { + deny all; + } +} +``` + +After you have saved the file, you need to create a symlink so the +server actually will read the file. + +```sh +ln -s /etc/nginx/sites-available/rss-bridge /etc/nginx/sites-enabled/rss-bridge +``` + +Then we have to create the folder where the service will reside in. + +```sh +mkdir -p /var/www/rss-bridge +cd /var/www/rss-bridge +``` + +Lets download the latest version of RSS-Bridge in the directory. + +The newest version can be found +[here](https://github.com/RSS-Bridge/rss-bridge/releases), at the time of +writing that is \"RSS-Bridge 2021-04-25.\" + +```sh +wget https://github.com/RSS-Bridge/rss-bridge/archive/refs/tags/2021-04-25.zip +``` + +Unzip the file: + +```sh +unzip 2021-04-25.zip +``` + +This will create a directory called rss-bridge-version-number, we now +want to move all the file contents of the newly created directory to the +one we are in + +```sh +mv rss-bridge-2021-04-25/* . +rm -rf rss-bridge-2021-04-25 2021-04-25.zip +``` + +Now all we need to do is grant read/write permissions and reload the web +server. + +```sh +chown -R www-data:www-data /var/www/rss-bridge +systemctl reload nginx +``` + +That\'s it, you should now have a working rss-bridge installed. But you +should definately get an SSL certifcate installed [which is done briefly here](/basic/certbot). + +- [handskemager.xyz](https://handskemager.xyz) +- Bitcoin: `bc1qhfjgwjzksf2auqjefwpvq20wvyugq3lhqgkxvu`{.crypto} +- Monero: + `88cPx6Gzv5RWRRJLstUt6hACF1BRKPp1RMka1ukyu2iuHT7iqzkNfMogYq3YdDAC8AAYRqmqQMkCgBXiwdD5Dvqw3LsPGLU`{.crypto} diff --git a/content/rss-feed.md b/content/rss-feed.md new file mode 100644 index 0000000..976f0e1 --- /dev/null +++ b/content/rss-feed.md @@ -0,0 +1,95 @@ +--- +title: "Creating an RSS Feed" +tags: ["concepts"] +date: 2022-07-02 +draft: true +--- + +RSS feeds are an easy way to be notified about new content from various +websites, and they are easy to implement in your website. + +## How an RSS Feed Works + +Some websites with frequently changing content like blogs, podcasts, or +video sharing sites, will have a link to a file containing the RSS feed +and its items. + +When there is new content, a new item can be added to the RSS feed, and +old items can optionally be removed from the RSS feed. A user\'s feed +reader can check an RSS feed for new items and notify the user about +them or organize them. + +## Writing an RSS Feed + +RSS feeds are written as XML (e**x**tensible **m**arkup **l**anguage) +files, so they can be written and served similar to HTML webpages. + +We will start by creating a file for our RSS feed. Make sure the file +name ends with `.rss` or `.xml`. Then, write the following code in the +file: + +```xml +<?xml version="1.0" encoding="UTF-8" ?> +<rss version="2.0"> + <channel> + </channel> +</rss> +``` + +The `<rss>` tag specifies that there is an RSS feed in between the +`<rss>` and `</rss>` tags. `version="2.0"` specifies that version 2.0 of +RSS is used. The items in an RSS feed go in between the `<channel>` and +`</channel>` tags. + +### Title, Description, and Link + +Now we will write a title and description for our RSS feed, as well as a +link to the webpage that the RSS feed goes with. In this example, we +will be writing an RSS feed for a blog called **SiCh\'s Blog**. + +In between the `<channel>` and `</channel>` tags, the `<title>` tag will +be used to label the feed as **SiCh\'s Blog**. The `<description>` +and `<link>` tags are used for the description of the feed and a link to +the corresponding webpage. + +```xml +<channel> + <title>SiCh's Blog</title> + <description>SiCh's writings and ideas</description> + <link>https://example.org/blog</link> +</channel> +``` + +{{< img src="/pix/rss-01.png" alt="SiCh's blog feed" link="/pix/rss-01.png" >}} + +### Feed Items + +Now we will add items to the RSS feed. These items are listed in the +user\'s feed reader and can represent different content on a page such +as blog posts or videos. In this example, there is a blog post called +**RSS is Amazing!**. + +The `<item>` tag is used to add items to the RSS feed. An item is given +a title using the `<title>` tag to label the item. The item will have a +link to its webpage using the `<link>` tag and an item description using +the `<description>` tag. + +The date and time of an item can be specified using the `<pubDate>` tag. +The date and time **must follow a specific format**. In the example +below, the item was posted on **Friday, October 1, 2021 at 2:27 PM in +the -0400 time zone**. + +```xml +<item> + <title>RSS is Amazing!</title> + <link>https://example.org/blog/2021-10-1-rss</link> + <description>RSS is a good notification system.</description> + <pubDate>Fri, 1 Oct 2021 14:27:00 -0400</pubDate> + </item> +``` + +{{< img src="/pix/rss-02.png" alt="SiCh's Blog feed with an item" link="/pix/rss-02.png" >}} + +## Contributor + +[ClosedGL](https://closedgl.xyz) diff --git a/content/rss-full-text.md b/content/rss-full-text.md new file mode 100644 index 0000000..995797d --- /dev/null +++ b/content/rss-full-text.md @@ -0,0 +1,204 @@ +--- +title: "RSS Full Text" +date: 2025-07-01 +tags: ["service"] +icon: "rss.svg" +short_desc: "Creates RSS full text feeds." +--- + +[fivefilters full-text-rss](https://www.fivefilters.org/full-text-rss/) +is Full-Text RSS service. Free open source RSS feeds usually provide +the summary or limited lines of URL contents. There is a way to see +the entire web page with text-based web browser such as lynx, w3m, and so on. +However, I want to do everything in [newsboat](https://github.com/newsboat/newsboat). +With this, you can retrieve the full-text of individual articles or +complete full-text RSS feeds. It enriches third-party RSS feeds with +full text articles. + +## Installation + +### Setting Up and Configuring + +Check PHP version (e.g., php7.4-fpm). Adjust in later steps accordingly. + +```sh +sudo apt update +sudo apt install nginx php php-fpm php-tidy git unzip certbot python3-certbot-nginx +``` + +Download Full-Text RSS + +```sh +cd /var/www +sudo git clone https://bitbucket.org/fivefilters/full-text-rss.git +cd full-text-rss +sudo git reset --hard 384d52fd83361ffd6e7f28bd39b322970a015a28 +``` + +Download Full-Text-RSS site config + +```sh +sudo git clone https://github.com/fivefilters/ftr-site-config site_config +``` + +Set permissions: + +```sh +sudo mkdir -p cache/rss +sudo chown -R www-data:www-data cache site_config +sudo chmod -R 777 cache site_config +``` + +### Configuring nginx & cerbot + +Create Nginx Config with Clean /feed + Rate Limiting + +Create a new site config: + +```sh +sudo nano /etc/nginx/sites-available/fulltextrss +``` + +Paste this (adjust php7.4-fpm.sock if needed): + +```nginx +# Rate limiting zone: 10 req/min per IP +limit_req_zone $binary_remote_addr zone=ratelimit:10m rate=10r/m; + +server { + listen 80; + server_name rss.thesiah.xyz; # Change to your domain + + root /var/www/full-text-rss; + index index.php; + + # Rewrite clean URL /feed?url=... to makefulltextfeed.php + location /feed { + rewrite ^/feed$ /makefulltextfeed.php last; + limit_req zone=ratelimit burst=5; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; + } + + location ~ /\.ht { + deny all; + } +} +``` + +Enable nginx on the site: + +```sh +sudo ln -s /etc/nginx/sites-available/fulltextrss /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx +``` + +Secure with HTTPS (Certbot) + +```sh +sudo certbot --nginx -d rss.thesiah.xyz +``` + +### Custom Config + +Add custom_config.php: +Save to: /var/www/full-text-rss/custom_config.php + +```php +<?php +/* Full-Text RSS config */ +if (!isset($options)) $options = new stdClass(); +$options->enabled = true; +$options->debug = true; +$options->default_entries = 200; +$options->max_entries = 1000; +$options->content = 'user'; +$options->summary = 'user'; +$options->rewrite_relative_urls = true; +$options->exclude_items_on_fail = 'user'; +$options->singlepage = true; +$options->multipage = true; +$options->caching = true; +$options->cache_time = 120; +$options->cache_dir = dirname(__FILE__).'/cache'; +$options->message_to_prepend = ''; +$options->message_to_append = ''; +$options->error_message = '[unable to retrieve full-text content]'; +$options->keep_enclosures = true; +$options->detect_language = 'user'; +$options->user_submitted_config = false; +$options->remove_native_ads = false; +$options->admin_credentials = array('username'=>'admin', 'password'=>getenv('FTR_ADMIN_PASSWORD')); +$options->allowed_urls = array(); +$options->blocked_urls = array(); +$options->key_required = false; +$options->api_keys = array(); +$options->default_entries_with_key = 5; +$options->max_entries_with_key = 10; +$options->xss_filter = 'user'; +$options->favour_feed_titles = 'user'; +$options->allowed_parsers = array('libxml', 'html5php'); +$options->allow_parser_override = true; +$options->cors = false; +$options->proxy_servers = array(); +$options->proxy = true; +$options->allow_proxy_override = true; +$options->apc = true; +$options->smart_cache = true; +$options->fingerprints = array( + '<meta name="generator" content="Posterous"' => array('hostname'=>'fingerprint.posterous.com', 'head'=>true), + '<meta content=\'blogger\' name=\'generator\'' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true), + '<meta name="generator" content="Blogger"' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true), + '<meta name="generator" content="WordPress' => array('hostname'=>'fingerprint.wordpress.com', 'head'=>true) +); +$options->rewrite_url = array( + 'docs.google.com' => array('/Doc?' => '/View?'), + 'tnr.com' => array('tnr.com/article/' => 'tnr.com/print/article/'), + '.m.wikipedia.org' => array('.m.wikipedia.org' => '.wikipedia.org'), + 'm.vanityfair.com' => array('m.vanityfair.com' => 'www.vanityfair.com') +); +$options->content_type_exc = array( + 'application/pdf' => array('action'=>'link', 'name'=>'PDF'), + 'image' => array('action'=>'link', 'name'=>'Image'), + 'audio' => array('action'=>'link', 'name'=>'Audio'), + 'video' => array('action'=>'link', 'name'=>'Video') + ); +$options->cache_directory_level = 0; +$options->cache_cleanup = 100; +if (!defined('_FF_FTR_VERSION')) define('_FF_FTR_VERSION', '3.5'); +if (basename(__FILE__) == 'config.php') { + if (file_exists(dirname(__FILE__).'/custom_config.php')) { + require_once dirname(__FILE__).'/custom_config.php'; + } + + foreach ($options as $_key=>&$_val) { + $_key = "ftr_$_key"; + if (($_env = getenv($_key)) !== false) { + if (is_array($_val)) { + if ($_key === 'ftr_admin_credentials') { + $_val = array_combine(array('username', 'password'), array_map('trim', explode(':', $_env, 2))); + if ($_val === false) $_val = array('username'=>'admin', 'password'=>''); + } + } elseif ($_env === 'true' || $_env === 'false') { + $_val = ($_env === 'true'); + } elseif (is_numeric($_env)) { + $_val = (int)$_env; + $_val = $_env; + } + } + } + unset($_key, $_val, $_env); +} +``` + +### Local host + +Visit http://localhost:80 for the integrated web UI + +{{<img src="/pix/rss-webui.png" alt="A screenshot of the Full Text RSS" >}} + +Article extraction: http://localhost/extract.php?url=[url] +Feed conversion: http://localhost/makefulltextfeed.php?url=[url] diff --git a/content/rsync.md b/content/rsync.md new file mode 100644 index 0000000..b2ccc07 --- /dev/null +++ b/content/rsync.md @@ -0,0 +1,104 @@ +--- +title: "Rsync: Upload and Sync Files and Websites" +date: 2021-07-01 +img: 'rsync.png' +tags: ['server'] +--- + +rsync is a simple way to copy files and folders between your local computer and +server. While you can install [Nextcloud](/nextcloud) is a more normie-friendly +Dropbox/Google Drive-like way to share files, people familiar with the +command-line will find all they need in the simple `rsync` command. + +It not only makes file-transfer easy, but it allows you to build and +maintain your website offline, then easily upload it to the proper +directory on your server so you don\'t need to constantly be logged into +your server to modify your site. + +## Installing rsync + +Run the following on your server *and* on your local machine. + +```sh +apt install rsync +``` + +## Uploading files with rsync + +From your local machine you can upload files to your server like this: + +```sh +rsync -rtvzP /path/to/file root@example.org:/path/on/the/server +``` + +You will be prompted for the root password and then uploading will +commence. + +If you omit **root@**, rsync will not attempt to log in as root, but +whatever your local username is. + +### Options to rsync + +In this command, we give several options to rsync. You can remove some of these +or add to them based on your needs: + +- `-r` -- run recurssively (include directories) +- `-t` -- transfer modification times, which allows skipping files + that have not been modified on future uploads +- `-v` -- visual, show files uploaded +- `-z` -- compress files for upload +- `-P` -- if uploading a large file and upload breaks, pick up where + we left off rather than reuploading the entire file + +Avoid using the commonly used `-a` option when uploading to a server. It can +transfer your local machine\'s user and group permissions to your +server, which might cause breakage. + +But `-a` is useful for making back-ups of important directories. It's an alias for many options at once (`-rlptgoD`)---read `man rsync` for the details. + +### Scriptability + +It\'s a good idea to build your website offline, then make an rsync +script or bash alias like the one above to upload the edited files when +you have made updates. + +### Password-less authentication + +To avoid having to manually input your password each upload, you can set +up [SSH keys](/sshkeys) to securely idenitify yourself and computer +as a trusted. + +### Picky trailing slashes + +rsync is very particular about trailing slashes. This is useful, but can +be confusing to some new users. Suppose we run the following wanting to +mirror our offline copy of our website in the directory we use on our +server (`/var/www/websitefiles/`): + +```sh +❌ rsync -rtvzP ~/websitefiles/ root@example.org:/var/www/websitefiles/ +``` + +This will *not actually do quite what we want*. It will take our local +`websitefiles` directory and put it *inside* `websitefiles` on the +remote machine, ending up with `/var/www/websitefiles/websitefiles`. + +Instead, remove the trailing slash from the remote server location: + +```sh +✅ rsync -rtvzP ~/websitefiles/ root@example.org:/var/www/websitefiles +``` + +`websitefiles/` has been replaced with `websitefiles`, and this will do +what we want. + +## Downloading files with rsync {#downloading-file-with-rsync} + +You may just as easily download files and directories from your server +with rsync: + +```sh +rsync -rtvzP root@example.org:/path/to/file /path/to/file +``` + +If you don't keep a local copy of your website or other things saved on a server🔒, it might be a good idea to set up a [cronjob](/cron) or just a normal script on your local computer that takes back-ups of your website in case of server failure! diff --git a/content/searxng.md b/content/searxng.md new file mode 100644 index 0000000..dc25f68 --- /dev/null +++ b/content/searxng.md @@ -0,0 +1,144 @@ +--- +title: "SearXNG" +date: 2022-05-16 +icon: 'searxng.svg' +tags: ['service'] +short_desc: 'Polls dozens of search engines to give you private and complete search results.' +--- + +SearXNG is a free internet metasearch engine which aggregates results +from more than 70 search services. This guide sets up a working instance +that can be accessed using a domain over HTTPS. Features include: + +- Self-hosted +- No user tracking +- No user profiling +- About 70 supported search engines +- Easy integration with any search engine +- Cookies are not used by default +- Secure, encrypted connections (HTTPS/SSL) + +## Installation + +Install the required packages. + +```sh +apt install git nginx nginx-extras -y +``` + +Open http and https ports. + +```sh +iptables -I INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT +iptables -I INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT +netfilter-persistent save +ufw allow 80 +ufw allow 443 +``` + +First we will create a user for SearX. + +``` +useradd -mr -d "/usr/local/searxng" -c 'Privacy-respecting metasearch engine' -s /bin/bash searxng +``` +Although the auto-install script below we create this user itself, we can go ahead and make it to give the cloned repository the correct permissions. + +Now we clone the SearXNG Repository into the `searx` user's home. + +```sh +git clone https://github.com/searxng/searxng /usr/local/searxng/searxng-src +cd /usr/local/searxng/searxng-src +``` + +Installing SearXNG. + +```sh +./utils/searxng.sh install all +``` + +## Configure Nginx + +Create a new file `/etc/nginx/sites-available/searxng.conf` and add the +following: + +```nginx +server { + + # Listens on http + listen 80; + listen [::]:80; + + # Your server name + server_name searx.{{<hl>}}example.org{{</hl>}} ; + + # If you want to log user activity, comment these + access_log /dev/null; + error_log /dev/null; + + # X-Frame-Options (XFO) header set to DENY + add_header X-Frame-Options "DENY"; + + # HTTP Strict Transport Security (HSTS) header + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; + + # Content Security Policy (CSP) + add_header Content-Security-Policy "default-src 'self';"; + + location / { + uwsgi_pass unix:///usr/local/searxng/run/socket; + + include uwsgi_params; + + uwsgi_param HTTP_HOST $host; + uwsgi_param HTTP_CONNECTION $http_connection; + + # see flaskfix.py + uwsgi_param HTTP_X_SCHEME $scheme; + uwsgi_param HTTP_X_SCRIPT_NAME /searxng; + + # see limiter.py + uwsgi_param HTTP_X_REAL_IP $remote_addr; + uwsgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for; + + } +} +``` + + +Now create a symbolic link to enable this site. + +```sh +ln -s /etc/nginx/sites-available/searxng.conf /etc/nginx/sites-enabled/searxng.conf +``` + +Restart Nginx and SearXNG. + +```sh +systemctl restart nginx +service uwsgi restart searxng +``` + +## Configure HTTPS with Certbot + +Install certbot. + +```sh +apt install python3-certbot-nginx +``` + +Install a Let\'s Encrypt SSL certificate to Nginx and optionally let it +configure HTTPS for you. [Detailed instructions and additional information](/basic/certbot). + +```sh +certbot --nginx +``` + +SearXNG should now be available from your domain. + +## Configuration + +You can change settings by editing `/etc/searxng/settings.yml`. + +## Contribution + +Author: goshawk22 -- [website](https://goshawk22.uk) diff --git a/content/selfhosting.md b/content/selfhosting.md new file mode 100644 index 0000000..0aa00b2 --- /dev/null +++ b/content/selfhosting.md @@ -0,0 +1,202 @@ +--- +title: "Self hosting" +date: 2020-08-19 +tags: ['server'] +--- +## Introduction + +When you have a(n old) computer lying around, and you have cheap +electricity and a good internet connection, self hosting might be a good +option for you. + +### Why would you choose selfhosting? + +- You have control over the hardware, and you can upgrade your server + in the future. For example: if you host a file server and your hard + drive goes full, you can simply add another hard drive or upgrade + it. +- No bandwith limits, storage limits, etc. (some VPSes have this) +- It **can** be cheaper than using a VPS. This only is the case if you + got the server for really cheap and your electricity is cheap. +- You can have a media server to consoom your content (for example + with `Jellyfin`). You can technically do this on a VPS, but that + will be more expensive than self hosting. If you have a media + server, you can stream media from your server to more devices. (I + recommend just downloading it on your device, but if you have + multiple devices, this could be a good solution) + +### Downsides + +Some possible downsides of choosing to host at home could be: + +- Your ISP not approving of what you\'re doing. Some ISP\'s do not + condone you hosting at home. Usually when this is the case, it could + be harder if you want to forward ports, or it could be impossible to + get a static IP address. Check your ISP\'s terms of service. + Sometimes, it will say that hosting a webserver, email server, and + more, is not allowed. +- This can also include blocked ports. ISPs can block certain ports to + the world. Sometimes ISPs only block 445/139 (which is for the + better as Samba, using these ports isn\'t really secure and it\'s + outdated). But some ISPs (sadly) block crucial ports like 80 + and/or 443. You need to check this before trying anything. If this + is the case, a way to get around it is to get another ISP or use an + alternative port. A great website to check this is: + [canyouseeme.org](https://canyouseeme.org/). You can also check if + you did the port forwaring correctly here. +- Security. Opening your network to the public could bring security + risks. For example, never open a Samba server to the public, because + it\'s a pretty old protocol, and it has some security + vulnerabilities. Be sure you are forwarding the right port, and + don\'t just forward random ports to the internet. Also, if you are + getting DDoSed, your ISP will temporarily shut down your whole + internet connection. +- When setting up an email server, it can be way harder to not have + your email show up as spam in other\'s people email. If you use a + VPS, this is way easier. +- Space, power consumption and noise. Of course, this differs per + server. + +Your mileage may vary, go and check each of these points, and see if +selfhosting is the right choice for you. Try and calculate your power +consumption and see if your electricity cost is not too expensive. + +For me, the upsides outweighed the downsides, which is why I chose to +host at home. But, this differs with each person and scenario. Go and +research what your exact situation is, before trying anything. Otherwise +you\'ll have to face some bad surprises. + +## Hardware + +### What kind of hardware should you choose? + +If you pay your own electricity bill, power consumption is a big factor. +Most old laptop computers are ideal in the sense that they don\'t use a +lot of power, and if the battery still works, you have a built-in UPS! +The bad thing is, most old laptop computers aren\'t that powerful, and +they lack in upgradability. (you shouldn\'t really be using anything +older than 2006, and I recommend at least a performance equivalant of a +Core 2 CPU) + +If you can find an energy efficient desktop (under 100W), that is a +great option. They are pretty upgradable and they don\'t use a lot of +power. They can also be pretty cheap, but old laptops are usually +cheaper. If you can afford new hardware, and are willing to build a PC, +you can find really power effecient CPU/motherboard combos, and they can +be cheap, for example the Celeron J3060. I recommend a low wattage power +supply or an effecient one for these kinds of builds. Pico PSUs are +pretty tiny and efficient solutions in these builds. + +Of course, if you don\'t pay your electricity bill or cost is not a +problem for you, you can use just about any old desktop (as long as +it\'s not from the 90\'s, I recommend at least a Core 2 chip again, or +an Athlon 64 X2). + +### Usecases + +Of course, hardware choices depend on the usecase. The above +recommendations I gave you work fine for e-mail server, webserver and +fileserver types of applications, but they will struggle to transcode +video if you are going to host a media server. You\'ll need a faster +CPU, but also a faster GPU. As an example, the Athlon 200GE or 3000G are +good and efficient choices for these builds. They are decent CPUs, but +also have a built in GPU that will transcode video just fine. + +If you need a lot of storage, go for a case with a lot of mounts for +hard drives, this way you can easily mount multiple hard drives. Pros of +multiple hard drives are redundancy and speed. Cons could be that they +create more heat and noise. You can\'t use a laptop if you want multiple +drives, except if you use a hard drive caddy for the CD/DVD drive bay. +Some business laptops even support RAID 1 (redundancy) and RAID 0 (speed +and more storage, but you lose your files if one hard drive breaks) this +way. + +## Getting started + +### Installing Debian + +Once you have the machine, you can install the OS. I recommend Debian, +as all of the guides on this website are Debian specific. Debian just +werks as a server OS. + +You\'ll need to burn a Debian install image onto a USB flash drive or a +CD. You can download the image +[here](https://www.debian.org/CD/netinst/), and you can also find +information on how to burn the image onto a USB flash drive or CD there. + +While installing Debian, do not install any desktop environment. But +install an SSH server when you get the chance. Also leave webserver +unchecked, even if you want to use it as a webserver. You\'ll have a +chance to install this later. + +### Port forwaring + +Every time you are going to set up a new server program, you need to +forward a port corresponding to that program. For example, HTTP is port +80, HTTPS is 443, etc. You need to set this up on your router\'s NAT +settings (sometimes just called port forwarding, this differs per +router). These steps differ for each router. Refer to your routers +manual. A simple command to see what your servers IP address is, is to +run `ifconfig` on your server. This shows a lot of network info, but it +will also show your local IP address needed for port forwarding. + +Basic ports: + +- SSH: port 22 (open this port if you want to admin your server + outside your network) +- HTTP: port 80 (open this port if you want basic webserver + functionality) +- HTTPS: port 443 (you should open this port if you are setting up a + webserver because encryption) + +### Static or dynamic IP address + +If you want to host your server at home, make sure you have a static IP +address, or you can change your dynamic IP address to a static one. +Refer to your router settings, some ISPs will have options on this here. +If you can\'t find anything on this, get in touch with your ISP. + +Once you\'ve made sure you have a static IP address, you can find out +what the IP address is with various websites. You can use a search +engine to easily find this out. Write this down as you\'ll need it +later. + +Once you\'re done, you can pretty much follow every guide on this +website, the only difference is that you\'ll need to forward the ports +you\'ll be using for the server. + +### Finding the ports you\'ll need to forward + +If you need to know what port you\'ll need to forward, there\'s a +command for that. Just type `netstat -tulpn` in your servers command +line. If you want to see the name of the programs, you need to run it as +a root user. You can do this by putting `sudo` before the command. + +```txt +Local Address State PID/Program name +0.0.0.0:25 LISTEN 887/master +0.0.0.0:1883 LISTEN 22452/mosquitto +0.0.0.0:445 LISTEN 798/smbd +0.0.0.0:993 LISTEN 381/dovecot +127.0.0.1:3306 LISTEN 560/mysqld +0.0.0.0:587 LISTEN 887/master +0.0.0.0:139 LISTEN 798/smbd +127.0.1.1:12301 LISTEN 412/opendkim +0.0.0.0:143 LISTEN 381/dovecot +0.0.0.0:465 LISTEN 887/master +0.0.0.0:22 LISTEN 472/sshd +:::25 LISTEN 887/master +:::443 LISTEN 1769/apache2 +:::1883 LISTEN 22452/mosquitto +:::445 LISTEN 798/smbd +``` + +*Example output* + +In this example, if you need to find the port number from `dovecot`, you +can look for it in the `Program name` column. Then you can see in the +local address column that the reported local address is `0.0.0.0:993`. +You need to look for the part after the semicolon. In this case it\'s +993. So you\'ll need to forward port 993. + +*Written by [hiddej](https://github.com/hidde-j)* diff --git a/content/slides_ed25519 b/content/slides_ed25519 new file mode 100644 index 0000000..7750d83 --- /dev/null +++ b/content/slides_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz +c2gtZWQyNTUxOQAAACDNzIc10QVWz15akz5ev9w53ZkdTeFCcIYbTxy/PfMqnQAA +AIj5jdpX+Y3aVwAAAAtzc2gtZWQyNTUxOQAAACDNzIc10QVWz15akz5ev9w53Zkd +TeFCcIYbTxy/PfMqnQAAAEBcCuTzm+t9HccmpdBu3tSm4xHjkSDpkRj9w1CyubmN +7s3MhzXRBVbPXlqTPl6/3DndmR1N4UJwhhtPHL898yqdAAAAAAECAwQF +-----END OPENSSH PRIVATE KEY----- diff --git a/content/slides_ed25519.pub b/content/slides_ed25519.pub new file mode 100644 index 0000000..2bf3253 --- /dev/null +++ b/content/slides_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM3MhzXRBVbPXlqTPl6/3DndmR1N4UJwhhtPHL898yqd si@t480 diff --git a/content/ssh-advanced.md b/content/ssh-advanced.md new file mode 100644 index 0000000..6c37ee9 --- /dev/null +++ b/content/ssh-advanced.md @@ -0,0 +1,239 @@ +--- +title: "SSH - Advanced Usage" +date: 2022-07-01 +tags: ['server'] +--- + +## Introduction + +This page is dedicated to advanced SSH usage examples. We will discuss +the following concepts: + +- config files (for client) +- tunneling +- jumping + +## Config files + +Config files allow you to specify certain rules for all or chosen hosts. +The file has a really simple structure. It is divided into sections +which begin with the `Host` keyword. Sections are read one by one and +**the first matching section takes precedence over the remaining +sections**---you write more specific sections at the top and the more +general sections below. + +### Why even bother? + +You might say that SSH client doesn\'t need any special configuration - +you just type user@host and that\'s it. Well, what happens when you +manage multiple servers? Maybe you want to use a different pair of keys +for each servers? Maybe the server uses a port other than the default 22 +to avoid automated bots trying to log in? + +That\'s where config files come in handy! + +### Example scenario + +Let\'s assume that you manage 3 servers, with the following access info: + +1. very.long.hostname.example1.com + - user: admin + - port: 22 + - key name: id_rsa +2. example2.com + - user: billthemaster + - port: 2222 + - key name: example2_ecdsa +3. 192.168.133.7 + - user: management + - port: 22 + - key name: id_rsa + +You got tired having to always specify the identity file location with +the `-i` option and the port with `-p` option for example2.com. Don\'t +even mention `admin@very.long.hostname.example1.com`! + +In the given example, the config file could look like this: + +```text +Host server1 + HostName very.long.hostname.example1.com + User admin + IdentityFile ~/.ssh/id_rsa + +Host server2 + HostName example2.com + Port 2222 + User billthemaster + IdentityFile ~/.ssh/example2_ecdsa + +Host server3 + HostName 192.168.133.7 + User management + IdentityFile ~/.ssh/id_rsa + +Host * + IdentityFile /path/to/some/other/key + ``` + +You can see here usage of `Host *`. Options specified in this section +will affect all other hosts. + +### But where do I put this file? + +SSH looks for the options in the following order: + +1. command line arguments +2. `~/.ssh/config` +3. `/etc/ssh/ssh_config` + +You can also specify a custom path with the `-F` argument, for example: + +```sh +ssh -F ~/Documents/projects/someproject/config/ssh production +``` + +\...or discard any config file: + +```sh +ssh -F /dev/null username@hostname +``` + +There\'s more to ssh config files, but I direct you to `man ssh_config` +for more information + +## SSH Tunneling (\"port forwarding\") + +SSH tunneling gives you the ability to route TCP traffic from your +location to the remote server or the other way around (if server allows +for this). Thanks to it, you can set up a secure connection with a +service that doesn\'t provide any encryption by default. You can treat +it like a lite VPN. + +You can for example access your SQL server via SSH without opening the +port for public - you just need SSH port opened on the server\'s +firewall. It\'s also a great way of creating a secure channel for +connecting with other hosts on the server\'s network. + +### Local to remote + +You can route traffic from your local network to the remote server\'s +network by using the `-L` option. Let\'s say you want to access a MySQL +service on the remote server. You can tell SSH to route any traffic that +comes to your 3000 port to port 3306 on the remote server with the +following example: + +```sh +ssh -L 3000:localhost:3306 username@example.com +``` + +The above command states that anyone connecting to your port 3000 will +be routed via the SSH connection to the localhost:3306 from the remote +server\'s perspective + +If you can\'t understand the above description, let\'s take a look at +another example: + +```sh +ssh -L localhost:8080:192.168.178.25:80 username@example.com +``` + +The above command states that any traffic coming from your device (and +only yours, because of `localhost`) will be routed via the SSH channel +to `192.168.178.25:80` in the server\'s network. + +In general, the argument\'s structure is as follows: + +```sh +-L [local_address:][local_port]:[remote_address]:[remote_port] +``` + +The `local_address` can be your LAN IP, `localhost` or any other address +that your device has. Depending on it, other devices in the specified +network will be able to connect to you or not. + +The `remote_address` can be any address reachable from the server. + +You can, of course, route multiple ports. For example: + +```sh +ssh -L 8000:localhost:8000 -L 8001:localhost:8001 username@example.com +``` + +Please, remember, this works **only** on TCP based services, **not** UDP +based. + +### Remote to local + +There might come a need for you to open your locally running service +(for example a game server) to external connections. Let\'s say you +can\'t or don\'t want to set up port forwarding on your router. + +You can use SSH to forward any traffic that is coming to a port on +remote server to a port on your local network host. The same as in the +case \"Local to remote\", but the other way around. + +However, there is one additional step that is neccessary and requires +you to have a root access to the remote server. You have to edit +`/etc/ssh/sshd_config` file, to instruct SSH server to route traffic to +the other end of SSH connection - your device.\ +Find and uncomment or append the one of the following lines to the file: + +```text +GatewayPorts yes # to allow all remote devices +GatewayPorts clientspecified # to allow only specific remote devices +``` + +You can then specify the forwarding rule with the `-R` option, for +example open `192.168.178.2:21` on your local network, to be accessible +from a remote server on port 2100: + +```sh +ssh -R 2100:localhost:21 username@example.com +``` + +\...or provide access only to your friend with an IP `111.111.111.111`: + +```sh +ssh -R 111.111.111.111:2100:localhost:21 username@example.com +``` + +You can replace `localhost` with any host accessible from your local +device, for example your local media server etc. + +## SSH Jumping + +Jumping is a method of connecting to a target via one or more +intermediate servers. This can be used to access servers behind +firewalls etc. All connections on the chain are encrypted and routed via +SSH. + +You can easily jump as shown in the following example: + +```sh +ssh -J username1@example1.com username2@example2.com +``` + +You can also specify multiple intermediaries, by separating them with a +comma: + +```sh +ssh -J username1@example2.com,username2@example.com username3@example3.com +``` + +There is also a possibility to set up \"jumping\" connection in a config +file: + +```text +Host intermediary1 + HostName target.intermediary-example.com + User john + +Host target1 + HostName target.example.com + ProxyJump intermediary1 + +Host target2 + HostName target2.example.com + ProxyJump username@example1.com + ``` diff --git a/content/sshkeys.md b/content/sshkeys.md new file mode 100644 index 0000000..7c39413 --- /dev/null +++ b/content/sshkeys.md @@ -0,0 +1,169 @@ +--- +title: "Log on with SSH Keys" +date: 2021-06-29 +tags: ['server'] +--- +Let\'s generate and use SSH keys on our computer. This allows us to +ensure our identity better than a password ever could. This allows us to +do two main things: + +1. **Password-less login**: With SSH keys, we can permanently designate + our profile on our local computer as safe for our server, allowing + us to bypass password verification when logging into our server. +2. **Prevent hacking**: Since we no longer need a password to log in, + we can simply deactivate password logins on our server altogether, + which prevents hacking from people who may be so lucky as to guess + our password! + +In other words, using an SSH key to login is **both safer, faster and +easier**. + +This is especially useful once you start making scripts on your computer +that interact with your server. You can upload files in the background, +edit your spam filters or anything else from your local computer without +having to input your password each time you touch the server. + +## Generate an SSH key pair + +Generating an SSH key is simple. Just run: + +```sh +ssh-keygen +``` + +It will prompt you for several options and you can generally chose the +default options in each case. It will ask you to optionally include a +password on your SSH key. I generally recommend against this unless you +happen to be using a computer where you don\'t have root access but +someone else does (it does minimize the ease of using an SSH key in our +case). + +### What does this SSH key do? + +Now whenever you use `ssh` to log into a server, you have the public key +of this SSH key pair as your identifier. You can tell your server to +trust this key and it will automatically allow password-less logins from +this computer. + +### Backing up your key + +We will do that momentarily, but first, I recommend you backup your +newly generated key if you plan to use it. If we disable logins to this +one key and then lose the key, we might be locked out of our server. + +I suggest copying your entire `~/.ssh/` directory (user-specific) to a +USB drive and storing it securely. You may also copy it to the same +place on another computer to use the key there. + +## Making your server trust your key. + +Now that you have generated an SSH key, just run the following: + +```sh +ssh-copy-id root@yourdomain.com +``` + +The command will ask for your server\'s root password and log you in +briefly. What this does is that it puts your public SSH key fingerprint +on your server in a file `/root/.ssh/authorized_keys`. This file in turn +allows approved SSH keys to log in without passwords. + +Note that you can also replace **root** with a username of an account on +the server if you had made a non-root user that you\'d like to easily +log into as well. For the username **user**, it will also store the key +in `/home/user/.ssh/authorized_keys`. + +To test if this has worked, now try logging in normally to your server +with ssh: + +```sh +ssh root@yourdomain.com +``` + +It should now let you log in without a password prompt! + +If you find that this does not work try running the following, make sure +you are in the directory where the keys where created. + +```sh +chmod 700 ~/.ssh/ +chmod 644 ~/.ssh/id_rsa.pub +chmod 600 ~/.ssh/id_rsa +chmod 644 ~/.ssh/authorized_keys +``` + +For whatever reason these files due not have the correct permissions +set, as ssh is very picky about correct file permissions this can cause +errors. The above will fix these. + +## Disabling Password Logins for Security + +Once we have authorized ssh keys for all the devices we need, we can +actually just disable password logins. If you\'ve ever looked at your +system logs (`journalctl -xe`) you will find that there are always +hundreds of random Chinese computers trying to brute force every server +connected to the internet with random passwords. They are usually +unsuccessful, but let\'s make it **impossible** for them. + +Log into your server and open the `/etc/ssh/sshd_config` file. Here we +can set settings for our SSH daemon that receives SSH requests. + +Now find, uncomment or create the following three lines and set them all +to **no**: + +```sh +PasswordAuthentication no +ChallengeResponseAuthentication no +UsePAM no +``` + +Once we\'ve done that, we will reload our SSH daemon: + +```sh +systemctl reload sshd +``` + +### **Warning:** + +It is possible that your ssh configuration +will be overridden by the default configuration added when creating +the VPS, which will leave you vulnerable to brute force attacks. To +prevent this, remove the configuration file using the following +command: + +```sh +rm /etc/ssh/sshd_config/50-cloud-init.conf +``` + +Also verify that the `/etc/ssh/ssh_config.d/` path is empty. If not, +make sure that the configuration files in that folder are not +overriding yours. + +### We\'re done! + +Now you can log in quickly and password-less-ly to your server, despite +the fact that it is now more secure than ever! + +With these settings, even if a hacker steals or perfectly guesses an +account password, they still cannot log in without an approved SSH key! + +## What if I lose my SSH key?! + +Firstly, don\'t do this. Take every precaution that you have a backup. + +If this does happen, Vultr and most other VPS providers will have a way +out. Log onto their website and select the server you want to log into. + +{{< img src="/pix/ssh-01.png" alt="vultr login" >}} + +In the image above, to the right of your VPS name are a series of icons. +Click on the computer screen-like icon which is the leftmost one. + +This will open up a browser window emulating a terminal and you can +always login with your password here, since logins here count as being +local---they do not use SSH and therefore can indeed validate with +your password even if you have disabled it over SSH. + +From here, simply reverse the settings we set above and you can log in +via SSH with a password and reapprove a newly created SSH key or +whatever you want to do. diff --git a/content/standalone.md b/content/standalone.md new file mode 100644 index 0000000..4f8d2a0 --- /dev/null +++ b/content/standalone.md @@ -0,0 +1,40 @@ +--- +title: "Certbot on Standalone Domains and Subdomains" +date: 2021-07-02 +tags: ['server'] +--- + +The command `certbot --nginx` will take an unencrypted website on an +Nginx configuration file, get a certificate for it and change the +configuration to use that certificate and thus HTTPS. + +Sometimes, however, you are given an Nginx configuration template that +already has encryption/HTTPS, so running the automated `certbot --nginx` +is not possible, as it will simply give an error saying that the +certicate that Nginx is looking for doesn\'t already exist and thus the +Nginx config is broken. + +So suppose you want to get a certificate for **pleroma.example.org** +because you are installing Pleroma and the configuration file +presupposes a certificate. In this case you would want to run this: + +```sh +systemctl stop nginx +certbot certonly --standalone -d pleroma.example.org +systemctl start nginx +``` + +What we do here is temporarily turn off Nginx, then run a `certonly` +subcommand that generates a certificate for the domain without changing +or caring about the Nginx configuration. Then we reactivate Nginx, thus +turning back on our webserver. + +The reason we deactivate Nginx is that it uses the ports that Certbot +will want to bind to, and thus we must temporarily turn Nginx off to let +Certbot use those ports. (What it actually does is spin up a dummy +webserver that doesn\'t need to think about the Nginx configuration.) + +This is just a little note of something that might confuse people, but +the three commands above should suffice. If your site is still managed +by Nginx, it should still be able to renew with simple +`certbot renew --nginx` without a problem. diff --git a/content/tor.md b/content/tor.md new file mode 100644 index 0000000..d6b1875 --- /dev/null +++ b/content/tor.md @@ -0,0 +1,117 @@ +--- +title: "Tor" +date: 2021-06-30 +icon: "tor.svg" +tags: ["service"] +short_desc: "Set your site up privately on the 'dark web.'" +--- + +Now that you have a website, why not offer it on a private alternative +such as the onion network? + +## Setting up Tor + +### Installing Tor + +First, we need to ensure that our CPU architecture is supported. Ensure +that it is either amd64, arm64, or i386: + + dpkg --print-architecture + +We need to [add the Tor repos to our +system](https://support.torproject.org/apt/tor-deb-repo/) to get the +latest version of Tor: + + apt install -y apt-transport-https gpg + echo "deb [signed-by=/usr/share/keyrings/deb.torproject.org-keyring.gpg] https://deb.torproject.org/torproject.org $(lsb_release -cs) main + deb-src [signed-by=/usr/share/keyrings/deb.torproject.org-keyring.gpg] https://deb.torproject.org/torproject.org $(lsb_release -cs) main" > /etc/apt/sources.list.d/tor.list + +Then we need to add the GPG keys to our keyring: + + curl -s https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor > /usr/share/keyrings/deb.torproject.org-keyring.gpg + +Now install Tor: + + apt update + apt install tor deb.torproject.org-keyring + +### Enabling Tor + +Next edit the file `/etc/tor/torrc`, uncommenting the following lines: + + HiddenServiceDir /var/lib/tor/hidden_service/ + HiddenServicePort 80 127.0.0.1:80 + +#### Optional: Running multiple onion services + +If you want to forward multiple virtual ports for a single onion +service, just add more HiddenServicePort lines (replace the 80 with any +unoccupied port). + +If you want to run multiple onion services from the same Tor client, +just add another HiddenServiceDir line. + +Now start and enable Tor at boot: + + systemctl enable --now tor + +If the next command outputs "active" in green you\'re golden! + + systemctl status tor + +Now your server is on the dark web. The following command will give you +your onion address: + + cat /var/lib/tor/hidden_service/hostname + +## Adding the Nginx Config + +From here, the steps are almost identical to setting up a normal website +configuration file. Follow the steps as if you were making a new website +in the webserver [tutorial](/basic/nginx) up until the server block of +code. Instead, paste this: + + server { + listen 127.0.0.1:80 ; + root /var/www/sich ; + index index.html ; + server_name your-onion-address.onion ; + } + +#### Clarification + +Nginx will listen on port 80 for your _server\'s_ localhost. + +The `root` line is the path to whichever website of yours you\'d like to +mirror. + +Now we are almost done, all we have to do is enable the site and reload +nginx which, is also covered in [the webserver +tutorial](/basic/nginx#enable). + +### Advertise your onion service + +You can add the Onion-Location header to your normal website to +advertise your onion service to Tor users. On your regular site\'s nginx +config, add the following line: + + server { + ... + add_header Onion-Location http://your-onion-address.onion$request_uri; + } + +After doing this and reloading nginx, when visiting your regular site +via Tor, you should see a \".onion available\" button on the address +bar, which should take you to the onion service. + +### Update regularly! + +Make sure to update Tor on a regular basis by running: + + apt update + apt install tor + +#### Note: + +You do **<u>not</u>** need to run certbot for an ssl certificate. +HTTP over tor is plenty secure! diff --git a/content/transmission.md b/content/transmission.md new file mode 100644 index 0000000..4930661 --- /dev/null +++ b/content/transmission.md @@ -0,0 +1,844 @@ +--- +title: "Transmission" +date: 2023-07-22 +icon: "transmission.png" +tags: ["service"] +short_desc: "Decentralized file-sharing with BitTorrent." +--- + +[Transmission] allows you to send and receive files via the BitTorrent +protocol. This tutorial shows you how to use Transmission to run a +"seedbox" - a server for downloading and seeding torrents. + +(For an explanation of BitTorrent, see [Appendix 1].) + +[Transmission]: https://transmissionbt.com/ +[Appendix 1]: #appendix-1-what-is-bittorrent + +## Installation + +The Transmission daemon is available in the Debian repositories: + +```sh +apt install transmission-daemon +``` + +Besides installing Transmission, this command creates: +* A user for running the service (`debian-transmission`) +* A default configuration file + (`/var/lib/transmission-daemon/info/settings.json`) +* A default service file + (`/etc/systemd/system/multi-user.target.wants/transmission-daemon.service`) + +## Configuration + +### Transmission-Daemon + +Any time you need to modify Transmission\'s configuration, you must stop +the `transmission-daemon` service. Otherwise, Transmission will +overwrite your changes. + +```sh +service transmission-daemon stop +``` + +Open `/var/lib/transmission-daemon/info/settings.json` to view +Transmission\'s configuration. The file should look something like this: + +```json +{ + "alt-speed-down": 50, + "alt-speed-enabled": false, + "alt-speed-time-begin": 540, + "alt-speed-time-day": 127, + "alt-speed-time-enabled": false, + "alt-speed-time-end": 1020, + "alt-speed-up": 50, + "bind-address-ipv4": "0.0.0.0", + "bind-address-ipv6": "::", + "blocklist-enabled": false, + "blocklist-url": "http://www.example.com/blocklist", + "cache-size-mb": 4, + "dht-enabled": true, + "download-dir": "/var/lib/transmission-daemon/downloads", + "download-limit": 100, + "download-limit-enabled": 0, + "download-queue-enabled": true, + "download-queue-size": 5, + "encryption": 1, + "idle-seeding-limit": 30, + "idle-seeding-limit-enabled": false, + "incomplete-dir": "/var/lib/transmission-daemon/Downloads", + "incomplete-dir-enabled": false, + "lpd-enabled": false, + "max-peers-global": 200, + "message-level": 1, + "peer-congestion-algorithm": "", + "peer-id-ttl-hours": 6, + "peer-limit-global": 200, + "peer-limit-per-torrent": 50, + "peer-port": 51413, + "peer-port-random-high": 65535, + "peer-port-random-low": 49152, + "peer-port-random-on-start": false, + "peer-socket-tos": "default", + "pex-enabled": true, + "port-forwarding-enabled": false, + "preallocation": 1, + "prefetch-enabled": true, + "queue-stalled-enabled": true, + "queue-stalled-minutes": 30, + "ratio-limit": 2, + "ratio-limit-enabled": false, + "rename-partial-files": true, + "rpc-authentication-required": true, + "rpc-bind-address": "0.0.0.0", + "rpc-enabled": true, + "rpc-host-whitelist": "", + "rpc-host-whitelist-enabled": true, + "rpc-password": "{224c4b5e26569d0baa8a161a68263253bbc69c26dnhxDeWg", + "rpc-port": 9091, + "rpc-url": "/transmission/", + "rpc-username": "transmission", + "rpc-whitelist": "127.0.0.1", + "rpc-whitelist-enabled": true, + "scrape-paused-torrents-enabled": true, + "script-torrent-done-enabled": false, + "script-torrent-done-filename": "", + "seed-queue-enabled": false, + "seed-queue-size": 10, + "speed-limit-down": 100, + "speed-limit-down-enabled": false, + "speed-limit-up": 100, + "speed-limit-up-enabled": false, + "start-added-torrents": true, + "trash-original-torrent-files": false, + "umask": 18, + "upload-limit": 100, + "upload-limit-enabled": 0, + "upload-slots-per-torrent": 14, + "utp-enabled": true +} +``` + +Here are the options you should definitely look at: +1. `download-dir` specifies where Transmission should save downloaded + torrents. (You can probably leave this at the default of + `/var/lib/transmission-daemon/downloads`.) If you change this, make + sure `debian-transmission` has permissions to use the directory. +2. `peer-port` specifies what port Transmission should listen on to + connect to peers. (You can probably leave this at the default of + `51413`.) +3. `rpc-password` specifies the password required to control + Transmission. Change this by typing it in as plaintext. When the + Transmission service starts, it will be hashed and prefixed with a + left curly bracket (`{`). +4. `rpc-port` specifies the port Transmission will listen on for remote + commands. (You can probably leave this at the default of `9091`, + unless you have another service listening on this port for some + reason.) +5. `rpc-username` specifies the username required to control + Transmission. The default is `transmission`, but feel free to change + this. + +### Firewall + +If `peer-port-random-on-start` is set to the default of `false`, your +firewall must allow TCP and UDP traffic on the `peer-port`. Assuming you +are using `ufw`, and `peer-port` is at the default of `51413`, enter: + +```sh +ufw allow 51413 +``` + +#### Note on Port Randomization + +If you set `peer-port-random-on-start` to `true`, your firewall must +allow both TCP and UDP traffic on the port range specified by +`peer-port-random-low` and `peer-port-random-high`. + +Assuming you are using `ufw`, and `peer-port-random-high` is `65535`, +and `peer-port-random-low` is `49152`, enter: + +```sh +ufw allow 49152:65535/tcp +ufw allow 49152:65535/udp +``` + +### Starting the Service + +After modifying and saving the `transmission-daemon` configuration, +start the service: + +```sh +service transmission-daemon start +``` + +Transmission will hash your password in the configuration. You should be +able to connect to the daemon with `transmission-remote` locally on the +server using your credentials as shown next. + +## Controlling Transmission Locally + +`transmission-daemon` runs your torrent session in the background. It is +controlled by an HTTP API that it serves on the `rpc-port` at +`localhost`. `transmission-remote` is the command line utility you can +use to control the daemon, and it was installed automatically when you +installed `transmission-daemon`. + +### Authentication + +You first need to authenticate `transmission-remote` using the username +and password you set up in `settings.json`. There are 2 basic ways you +can do this. + +#### .netrc File + +The first method is via a `.netrc` file in your home directory. The +advantage of this method is that you do not need to provide your +credentials every time you run a `transmission-remote` command. The +disadvantage is that your Transmission password is stored in your home +folder as plaintext. + +To add the necessary record to your `.netrc` file, run the following +command, where `<username>` is the `rpc-username`, and `<password>` is +the plaintext version of `rpc-password` in `settings.json`: + +```sh +echo "machine localhost login <username> password <password>" >> ~/.netrc +``` + +Then, to authenticate, run: + +```sh +transmission-remote --netrc +``` + +Subsequent `transmission-remote` commands will not require entering your +credentials. + +#### \-\-auth Flag + +The second method to authenticate is to include an `auth` flag in every +`transmission-remote` command you execute. Substituting your credentials +for `username` and `password`, you can enter the following command to +list your torrents: + +```sh +transmission-remote --auth=username:password --list +``` + +At this point, you should be able to use `transmission-remote` on your +server to manage your torrents. + +### Hosting Torrents + +Here is a cookbook of common `transmission-remote` commands for hosting +torrents. + +Add a torrent via a magnet link: + +```sh +transmission-remote --add "magnet:link" +``` + +Add a torrent via a .torrent file: + +```sh +transmission-remote --add "your.torrent" +``` + +List the status of your torrents (and get their numerical IDs): + +```sh +transmission-remote --list +``` + +Get information about a specific torrent (where `ID` is the torrent ID +from the prior command): + +```sh +transmission-remote --torrent=ID --info +``` + +Remove a torrent and keep its data (where `ID` is the torrent ID): + +```sh +transmission-remote --torrent=ID --remove +``` + +Remove a torrent and delete its data (where `ID` is the torrent ID): + +```sh +transmission-remote --torrent=ID --remove-and-delete +``` + +Get information about the current Transmission session: + +```sh +transmission-remote --session-info +``` + +Get statistics about the current Transmission session: + +```sh +transmission-remote --session-stats +``` + +### Downloading Completed Torrents via Secure Shell + +Completed torrent downloads will be saved in the directory indicated by +`download-dir` in your configuration. (This is +`/var/lib/transmission-daemon/downloads` by default.) + +You should be able to download those files and directories from your +seedbox using tools like [`rsync`], `(s)ftp`, and `scp`. + +[`rsync`]: ../rsync/ + +If this is sufficient for you, you do not need to configure Transmission +for remote access. + +## Creating New Torrents + +`transmission-create` is used to create torrents. It was installed +automatically on your server when you installed `transmission-daemon`. +You can use it on any machine that has it installed and has a copy of +the file or directory you want to share. + +(`transmission-edit` is also available to edit .torrent files. It can do +things like add and delete tracker urls. However, this tool tends to be +more useful when working with other\'s .torrent files and less so when +creating torrents from scratch.) + +### Creating the .torrent File + +Here is a template command for creating a .torrent file: + +```sh +transmission-create --outfile "my.torrent" \ + --comment "My cool torrent" \ + --tracker "https://tracker1.example.org/announce" \ + --tracker "https://tracker2.example.org/announce" \ + "path/to/my/file/or/directory" +``` + +* `outfile` specifies where to write the .torrent file. +* `comment` specifies a comment for the torrent. +* `tracker` specifies a torrent tracker to use. You can have multiple of + these. `udp://open.tracker.cl:1337/announce` is usually a good choice, + but there are many others. +* The path indicates the file or directory you want to make a torrent + of. + +### Generating the Magnet Link + +`transmission-show` is used to generate magnet links from .torrent +files, and it was installed when you installed `transmission-daemon`. +Given any .torrent file, you can run: + +```sh +transmission-show --magnet "my.torrent" +``` + +### Seeding Your New Torrent + +First, copy the file or directory that you are hosting to the download +directory (`download-dir`) specified in the `transmission-daemon` +configuration. If the `download-dir` is at the default, you could write: + +```sh +cp "the-file-or-directory-to-share" \ + "/var/lib/transmission-daemon/downloads/" +``` + +Then, add your torrent to Transmission via your .torrent file or magnet +link: + +```sh +transmission-remote --add "the-torrent-file-or-magnet-link" +``` + +Your server should begin seeding your torrent, and you can share it via +the .torrent file or magnet link. + +**Warning:** Make sure you copy the file or directory you are seeding to +the `download-dir` directory *before* adding the torrent to +Transmission. If you copy the source file/directory into your download +directory *after* adding the torrent, run `transmission-remote` to get +the ID of your torrent: + +```sh +transmission-remote --list +``` + +Then, where `ID` is the ID of the torrent, run this command so +Transmission will know it already has the data: + +```sh +transmission-remote --torrent=ID --verify +``` + +The torrent should then begin seeding. + +## Controlling Transmission Remotely + +At this point, you should be able to manage your seedbox locally by +using `transmission-remote` on your server via secure shell. However, it +may be convenient to also configure the box for remote access. You can +do this by exposing Transmission\'s HTTP API, which includes a web app. + +The Transmission web app acts as a graphical stand-in for +`transmission-remote`. You can manage your torrents and the daemon with +it. + +Similar to `transmission-remote` itself, however, you cannot download +completed torrents via the web app. (That requires serving the files via +a different channel, whether that be `rsync`, `sftp`, `scp`, `http(s)`, +etc. Serving completed torrents via `http(s)` is explained later.) + +Exposing Transmission\'s HTTP interface to the internet additionally +allows you to control your seedbox from a different machine using +`transmission-remote`. + +### Configuring Remote Access + +By default, `transmission-daemon` only allows RPC commands from +`localhost`. For remote access, it must allow connections from the IP +addresses you want to access the daemon from. The most direct way of +doing this is by disabling the whitelist, which allows all IP addresses, +but you can specify a whitelist if you like. + +Stop `transmission-daemon`: + +```sh +service transmission-daemon stop +``` + +Then, set `rpc-whitelist-enabled` to `false` in your configuration. This +makes it so that any IP address can connect and control +`transmission-daemon`. (You will just need your `rpc-username` and the +plaintext version of your `rpc-password` to authenticate.) + +Alternatively, if you want to use the whitelist, set +`rpc-whitelist-enabled` to `true`, and set `rpc-whitelist` to a +comma-separated list of IP addresses. (Asterisks are used as wildcards.) +For example, you could write: + +``` +101.125.137.168,89.72.*.221 +``` + +While you have the configuration open, take note of the value of +`rpc-port`, which is 9091 by default. This value will be necessary for +configuring remote access. + +After saving your configuration, start `transmission-daemon`: + +```sh +service transmission-daemon start +``` + +### Running Nginx as a Reverse Proxy + +It is possible to open remote access to `transmission-daemon` simply by +opening its `rpc-port` in the firewall, 9091 by default. This connection +will be run over insecure HTTP, so your username and password will be +sent unencrypted. While this may be acceptable when testing a system, it +is generally preferable to use a web server with TLS as a reverse proxy +to Transmission\'s HTTP interface. + +If you are already running nginx with working TLS, allowing access to +Transmission\'s web interface simply requires adding a `location` block +to your `server` block in your nginx configuration. Assuming `rpc-port` +is 9091, and `rpc-url` is `/transmission/` in your `transmission-daemon` +configuration, add the following block to your nginx configuration: + +```nginx +location /transmission/ { + proxy_pass http://localhost:9091/transmission/ ; +} +``` + +Reload nginx so your changes takes effect: + +```sh +nginx -s reload +``` + +At this point, if `example.org` is your domain, and you are connected +from a permitted IP address: +* The Transmission web app will be available at + `https://example.org/transmission/web/`. +* `transmission-remote` will be able to connect to + `https://example.org/transmission`. (Note the omission of the trailing + forward slash.) + +#### Serving Transmission at a Different Path + +By default, Transmission serves it\'s interface at the path +`/transmission/`. You can change this in the configuration, but note +that your chosen path must start and end with a forward slash. + +For example, to serve Transmission\'s interface at `/~luke/torrents/`: + +1. Stop the `transmission-daemon` service. +2. Set `rpc-url` in the configuration to your chosen path. That is + `/~luke/torrents/` in this example. +3. Modify the `location` block\'s path pattern and `proxy_pass` url in + your nginx configuration to use the new path (and the correct + `rpc-port`). For this example, that is: + +```nginx +location /~luke/torrents/ { + proxy_pass http://localhost:9091/~luke/torrents/ ; +} +``` + +4. Start the `transmission-daemon` service. +5. Reload nginx. + +The Transmission web app will then be accessible at +`https://example.org/~luke/torrents/web/`. `transmission-remote` will be +able to connect to `https://example.org/~luke/torrents`. + +### Connecting via a Browser + +Where `example.org` is your website, and `/transmission/` is the +`rpc-url` in your `transmission-daemon` configuration, point your web +browser to `https://example.org/transmission/web/`. After entering your +credentials into the login (using your `rpc-username` and plaintext +`rpc-password`), you will be greeted by the web interface with a list of +your torrents. + +Here is a Transmission instance that is downloading one torrent: + +{{<img src="/pix/transmission-web-interface.png" + alt="A screenshot of the Transmission web interface" >}} + +### Connecting via Transmission-Remote + +You can control `transmission-daemon` on your server from other machines +that have `transmission-remote` installed. You do this by calling +`transmission-remote` with a url consisting of the domain name (or IP), +the `rpc-port`, and the path specified by `rpc-url` in the configuration +(`/transmission/` by default) with the trailing forward slash omitted. +For example, after inserting your credentials for `username` and +`password`, assuming the `rpc-url` is at the default of +`/transmission/`, you could invoke the following command on your local +machine to list the status of the torrents on your server: + +```sh +transmission-remote https://example.org/transmission \ + --auth=username:password \ + --list +``` + +Note how the `rpc-url` is `/transmission/`, but `/transmission` is +specified in the command. + +**Warning:** The Transmission web app and `transmission-remote` both +allow you to make changes to Transmission\'s port settings. Be careful +change these, because you might also need to update your server\'s +firewall configuration. + +## Serving Complete Torrent Downloads via HTTP(S) + +The Transmission web interface and `transmission-remote` do not allow +you to download completed torrents from your seedbox via HTTP(S). +However, in some scenarios, downloading via HTTP(S) may be preferable +where shell access and other supporting tools (`rsync`, `scp`, `sftp`, +`ftp`, etc.) are unavailable on the client machine. Serving completed +torrent downloads involves configuring nginx to serve the `download-dir` +of `transmission-daemon`. + +(Serving completed torrent downloads via HTTP(S) does not require +exposing Transmission\'s HTTP API and web app.) + +**Warning:** The Transmission interfaces give you the option of saving +completed torrent downloads to directories other than the `download-dir` +specified in your `transmission-daemon` configuration. Downloading a +torrent to a different directory and not serving that directory with +nginx will prevent that completed torrent from being served to clients +via the static file server shown here. + +Assuming you wish to serve your completed torrents from the directory +`/downloads/` on your web server, and `download-dir` is at the default +of `/var/lib/transmission-daemon/downloads/`, you can add this +`location` block into the `server` block of your nginx configuration: + +```nginx +location /downloads { + root /var/lib/transmission-daemon/downloads ; + proxy_max_temp_file_size 0 ; + autoindex on ; +} +``` + +Note how the trailing forward slash has been omitted in both the +`location` pattern and the `root` path. + +The `proxy_max_temp_file_size` option prevents disk caching that would +potentially break nginx\'s ability to serve files larger than a few +gigabytes. + +If you omit the `autoindex` option or set it to `off`, nginx will not +show a directory listing of your downloaded torrents. (You will need the +direct link to download a given torrent.) + +After saving the configuration, reload nginx. + +Where `example.org` is your website, and assuming `autoindex` is `on`, +opening `https://example.org/downloads/` in a web browser should show a +list of links to download your completed torrents. + +While downloading via HTTP(S) can be convenient, resuming interrupted +downloads can be a nuisance. See [Appendix 2] for tips on how to combat +this. + +[Appendix 2]: #appendix-2-reliable-downloading-via-https + +### Preventing Unauthorized Downloading + +If you want to prevent others from downloading completed torrents via +HTTP(S) from your seedbox, you have a few options: +1. When defining the nginx `location` block, you can use some random + string for the path match pattern, like `/DJRmdL8HPn`. Only those who + know the path will able to download your completed torrents. +2. You can protect the directory with a username and password using + [HTTP basic authentication]. + +[HTTP basic authentication]: ../auth/ + +## Troubleshooting + +`journalctl` can be used to view the logs of `transmission-daemon`. For +example, you could run: + +```sh +journalctl | grep transmission-daemon +``` + +Transmission\'s [documentation] contains help and answers to common +questions. + +[documentation]: + https://github.com/transmission/transmission/blob/main/docs/README.md + +## Appendix 1: What is BitTorrent? + +Many protocols for sending files over the internet, such as Hypertext +Transfer Protocol (HTTP) and File Transfer Protocol (FTP), operate on a +\"client-server\" (or \"server-client\") model. A server will store a +file. A client will send a request for the file from the server. If the +request is accepted, the server will respond with the file. + +In contrast, BitTorrent is a decentralized, peer-to-peer, file-sharing +protocol. Instead of relying on a dedicated server, a file will be +assembled by downloading it in chunks from many different hosts. Anyone +who has the file (or pieces of it) can then help serve the file to +others. This makes file-sharing via BitTorrent much less susceptible to +data loss and downtime than the client-server model since the file can +be replicated and shared across a potentially large number of +independent hosts. + +The individual hosts are called \"peers\". The process of a host +offering their copy of the file for download to others is called +\"seeding\". The set of peers collectively hosting the file is called a +\"swarm\". + +The peers usually find out about each other using \"trackers\", +dedicated servers that help peers find those who possess or want a +specific file. Trackers are identified by URLs. A peer can \"announce\" +to a tracker that it possesses a specific file. If a peer wants to +download a file, the peer can ask the tracker for peers that possess the +file. Trackers do not actually transfer the torrent between peers. They +simply facilitate peer-discovery. + +The BitTorrent network also uses other mechanisms for peer-discovery, +including a \"DHT\", or Distributed Hash Table. Similar to trackers, +these help peers find each other. Unlike trackers, a DHT is entirely +peer-to-peer as it is based on a distributed data structure rather than +a dedicated server. The DHT that BitTorrent uses is called the Mainline +DHT. Most modern torrent clients will give you the option of using it to +help you find peers. (Transmission supports it.) + +Before downloading a desired file or directory, you will need its +.torrent file or magnet link. These are usually distributed via +webpages, and they contain metadata and other information required for +downloading the file, including: +* The cryptographic hash of the file for validating its integrity. (A + .torrent file will also include hashes for individual chunks of the + file.) +* The name of the torrent. +* A list of tracker URLs to use for finding peers. + +Once the .torrent file or magnet link has been imported into a torrent +client, the client will query the network to discover peers that possess +the file. The swarm will then work together to send the user the file in +chunks. The chunks will be cryptographically validated and assembled to +create the final file. After the user has downloaded the file (or even +if they only have pieces of it), they also can be part of the swarm by +helping to seed the file to others who want it. + +\"Leeching\" is when a user downloads torrents and does not seed them to +others. This practice hurts the overall functioning of the swarm and +will also usually reduce the bandwidth that other peers are willing to +dedicate to you in the future. Always reseed. 🌱 + +## Appendix 2: Reliable Downloading via HTTP(S) + +Downloading via HTTP(S) can be very convenient when shell access is +unavailable. It can also be very troublesome with large files due to +interrupted or corrupted downloads. Thankfully, utilities like `wget` +and `zsync` can help combat this. + +### wget + +`wget` supports resuming interrupted downloads. It isn\'t as robust for +this use case as other utilities (like `zsync`), but it can be +convenient because: +* It doesn\'t require any extra setup on your server. +* It comes preinstalled on most \*nix systems. + +Supposing you want to download a very large file from your web server +and save it to your current directory, you might run: + +```sh +wget https://example.org/downloads/large.file +``` + +If this command is stopped or interrupted, running it again with the +`--continue` flag will cause `wget` to resume your download: + +```sh +wget --continue https://example.org/downloads/large.file +``` + +If your network connection is particularly poor, you can also specify +the `--tries=0` flag. `wget` will retry connecting indefinitely, so you +don\'t need to run the command multiple times if it disconnects. + +One major downside of using `wget` is that the resumption of the +download is based on the difference between the file length on the +server and the length of the partial file on your disk. No cryptography +or checksum is used to validate the file's integrity. + +`wget` also supports downloading directories, but this can be finicky. +You might need to experiment with the arguments depending on the +contents of the directory. For example, assuming directory listing is +enabled in the relevant directory on your web server, you might run a +command like: + +```sh +wget --recursive --no-parent \ + https://example.org/downloads/large-directory/ +``` + +The `--recursive` flag indicates that `wget` should download the +contents of the directory as well as its subdirectories up to 5 levels +deep. + +The `--no-parent` flag indicates that `wget` should not download any +files at higher levels in the directory hierarchy. + +**Note:** Enabling `autoindex` for a directory in nginx implicitly +creates `index.html` files in the directory and its subdirectories from +the perspective of HTTP(S) clients like `wget`. However, the `--reject +index.html` flag is omitted in the above command because `wget` needs +the links in those index files to download all of the files in the +target directory. (In fact, for this reason, the above command might +potentially fail to download all the files in the directory if the +target directory contains `index.html` files.) Once the directory has +been downloaded to your disk, you would then need to delete the +`index.html` files that were created by the web server's directory +listing in your downloaded copy. Additionally, the actual directory +structure created on your disk with this example would be +`example.org/downloads/large-directory/`, not `large-directory/`. + +### zsync + +`zsync` is another option for more reliable HTTP(S) downloading. + +The advantages of `zsync` include: +* It offers significantly more data validation than `wget` by using + hashes and checksums. +* By using the `-i` flag, you can specify file chunks you have on disk + from the same or similar downloads to potentially accelerate the + current download. + +The disadvantages of `zsync` include: +* It does not usually come pre-installed on *nix systems. +* Unlike `wget`, it does not support downloading directories. It only + supports files. +* It must be installed on the client-side. +* It requires additional setup on the server-side. + +`zsync` is available in the Debian repositories. Install it on your +server by running: + +```sh +apt install zsync +``` + +(You will also need to install it on your client machine.) + +On your server, change your directory to your torrent download +directory, `/var/lib/transmission-daemon/downloads/` by default. Then, +run `zsyncmake` by providing the url and name of the file you want to +use `zsync` on: + +```sh +zsyncmake -u "https://example.org/downloads/large.file" large.file +``` + +This will create a new file with the same name as your original file but +with the `.zsync` extension added: `large.file.zsync` in this case. +(Note that if the file you are sharing changes, you need to regenerate +the `.zsync` file.) + +If you view your torrent download directory in a browser, and nginx has +`autoindex` turned `on`, you should notice the addition of the `.zsync` +file in the directory. + +On your HTTP(S) client, where the provided url is the link to the new +`.zsync` file, run: + +```sh +zsync "https://example.org/downloads/large.file.zsync" +``` + +If your download is interrupted, just run the command again, and `zsync` +will read your partial download, resume it, checksum it, and cleanly +assemble the target file, `large.file`. + +If your downloads directory is protected with HTTP basic authentication, +you can specify your credentials by adding an `-A` flag before the URL: + +```sh +zsync -A example.org=username:password \ + "https://example.org/downloads/large.file.zsync" +``` + +If you have a piece of the file with a different name or a different +version of the file, you can specify those pieces with the `-i` flag to +potentially reduce what `zsync` needs to fetch over the network: + +```sh +zsync -i "large.file.piece" -i "large.file.old" \ + "https://example.org/downloads/large.file.zsync" +``` + +`zsync` will attempt to look for file chunks in `large.file.piece` and +`large.file.old` that can be used to help assemble `large.file`. + +For example, if you have a Linux ISO on your computer, and you want to +download an updated version from your seedbox, there\'s a good chance +that only certain sections of the ISO changed from the version you +already have. You can specify the old version of the ISO you have with +the `-i` flag to potentially reuse chunks from the old version when +downloading the new ISO. + +--- + +*Written by: Luke Hamann* diff --git a/content/ufw.md b/content/ufw.md new file mode 100644 index 0000000..6b34630 --- /dev/null +++ b/content/ufw.md @@ -0,0 +1,223 @@ +--- +title: "Using UFW as a Firewall" +date: 2021-06-30 +tags: ['server'] +--- +**Uncomplicated Firewall** (UFW) is a front-facing program for the more +involved `iptables` firewall program installed in most GNU/Linux +distributions. We can use `ufw` to restrict machines on the internet to +only access the services (SSH, websites etc) you want them to, but it +can also be used to prevent programs on the computer itself from +accesing parts of the internet it shouldn\'t. + +## How to Get It + +Log into your server by pulling up a terminal and typing: + +```sh +ssh root@example.org +``` + +This command will attempt to log into your server and run a remote +shell. If you leave the settings default, it should prompt you for your +password, and you can just copy or type in the password from Vultr\'s +site. + +Some VPS providers automatically install `ufw`, but if you do not have +it installed already, install it in the typical way: + +```sh +apt install ufw +``` + +## First-Time Setup + +You can check the status of `ufw` right now by running: + +```sh +ufw status +``` + +Without any changes, it should report back `Status: inactive`. Let\'s +set it up so that only connections to SSH (standardized at port 22) are +allowed in, and then enable the firewall: + +**Careful!** Enabling `ufw` without allowing SSH will block you from +remoting to your server. Double-check that you have allowed SSH, and if +you have changed the default SSH port, put in *that* number instead. + +```sh +ufw default deny incoming # block all incoming connections by default +ufw allow in ssh # or: ufw allow in 22 +ufw enable +``` + +`ufw` has an internal list of protocols applications, and the ports used +by them. In this case, it knows SSH is on port 22. We\'ll go more in +detail how to view all protocols `ufw` knows about. By default, when you +allow an incoming port, it allows that port both on IPv4 and IPv6. + +With the firewall enabled and allowing only SSH in, all other ports are +protected from incoming requests. To view all your rules, run: + +```sh +ufw status verbose +``` + +A firewall that allows to connect to SSH and their website may look +like: + +```txt +Status: active +Logging: on (low) +Default: deny (incoming), allow (outgoing), deny (routed) +New profiles: skip + +To Action From +-- ------ ---- +22 (SSH) ALLOW IN Anywhere +80,443/tcp (WWW Full) ALLOW IN Anywhere +22 (SSH (v6)) ALLOW IN Anywhere (v6) +80,443/tcp (WWW Full (v6)) ALLOW IN Anywhere (v6) +``` + +If you want to delete e.g. the \'WWW Full\' rule, run: + +```sh +ufw delete allow in 'WWW Full' +ufw reload +``` + +## Enabling Common Services + +You have blocked all incoming ports but SSH, which means no outsiders +would be able to access other services, like an email server or your +website. You should look at the ports your services are open on and +enable them individually. Here is a list of a few common services: + +### Opening Port Numbers + +Suppose you install [a Gemini server](/gemini), which must broadcast +on port 1965. By default `ufw` blocks all incoming connections on all +ports, so whenever you install a new service like this you will have to +tell `ufw` to enable the desired port: + +```sh +ufw allow 1965 +``` + +### Websites: HTTP and HTTPS + +HTTP uses port 80 and HTTPS uses port 443. We can enable them like this: + +```sh +ufw allow 80 +ufw allow 443 +``` + +But `ufw` additionally knows the typical ports of common serives, so you +can also run this: + +```sh +ufw allow http +ufw allow https +``` + +And that will do the same thing. There are also other abbreviations for +common port lists: + +```sh +ufw allow in 'WWW Full' +``` + +To see these other \"apps\" that `ufw` knows by default, run +`ufw app list` + +### Email: IMAP, POP3, and SMTP + +```sh +ufw allow in IMAPS +ufw allow in POP3 +ufw allow in SMTP +ufw allow in 'Postfix SMTPS' +ufw allow in 'Mail Submission' +``` + +## Fine-Tuning Rules + +Instead of denying all ports by default, you may want to deny (ignores +incoming requests) or reject (explicitly tells requests they\'re not +allowed): + +```sh +ufw default allow in +ufw deny in PORT +ufw reject in PORT +ufw reload +``` + +You can add rules to comments to remember what they are there for: + +```sh +ufw allow in PORT comment 'Secret SSH' +ufw reload +ufw status verbose +``` + +Output: + +```txt +To Action From +-- ------ ---- +PORT ALLOW IN Anywhere # Secret SSH +PORT (v6) ALLOW IN Anywhere (v6) # Secret SSH +``` + +To deny outgoing ports: + +```sh +ufw deny out PORT +``` + +Ratelimiting is useful to protect against brute-force login attacks, +like in SSH. Only IPv4 is supported for now. Enable it by running: + +```sh +ufw limit PORT/tcp +``` + +To blocklist IP addresses: + +```sh +ufw deny from IP_ADDRESS +``` + +To read more what you can do with `ufw`, run: + +```sh +man ufw +``` + +## Recovering SSH {#recovering-from-losing-ssh} + +If you have accidentally firewalled yourself from logging on your +computer, you can recover access by using your VPS\'s virtual console. +On Vultr, this is on your VPS\'s menu. To the right of the server name, +It is the leftmost icon that looks like a monitor. + +{{< img src="/pix/ssh-01.png" link="/pix/ssh-01.png" alt="View Console" >}} + +Log in through there, and disable ufw by typing: + +```sh +ufw disable +``` + +## Further Reading + +- `man ufw` 👈 +- [Ubuntu Wiki: + UncomplicatedFirewall](https://wiki.ubuntu.com/UncomplicatedFirewall) +- [Gufw (Graphical UFW)](https://help.ubuntu.com/community/Gufw) + +**Contributor** - [shunter.xyz](https://shunter.xyz) diff --git a/content/wireguard.md b/content/wireguard.md new file mode 100644 index 0000000..c0d1879 --- /dev/null +++ b/content/wireguard.md @@ -0,0 +1,173 @@ +--- +title: Wireguard +date: 2022-07-26T00:00:00.000Z +icon: wireguard.svg +tags: + - service +short_desc: "Fast, Modern, Secure VPN Tunnel" +--- + +Looking for lightweight privacy on the go? Then consider hosting a WireGuard VPN service. +In addition to this setup guide, we'll also demonstrate how to tunnel +your WireGuard traffic through a TLS WebSocket connection to circumvent some +deep packet inspection systems. + +As an example, we'll be using a virtual 172.16.0.0/24 network, but any private ip range will suffice. + +## Installation + +### On the Server + +Install the WireGuard management tools: + + apt install wireguard + +Enable IPv4 forwarding by uncommenting the following line in `/etc/sysctl.d/99-sysctl.conf` + + net.ipv4.ip_forward=1 + +Run the following command to apply the change: + + sysctl -w net.ipv4.ip_forward=1 + +### On the Client + +Use your package manager to install the WireGuard Management Tools. +On Arch and Fedora based distros the package is `wireguard-tools`. For Debian based, it's listed above. + +Create the public and private keys for your machine: + + sudo bash -c "umask 077 ; wg genkey > /etc/wireguard/client_priv.key" + sudo bash -c "wg pubkey < /etc/wireguard/client_priv.key > /etc/wireguard/client_pub.key" + +### Back to the Server + +Generate the public and private keys for your server: + + umask 077 ; wg genkey > /etc/wireguard/server_priv.key + wg pubkey < /etc/wireguard/server_priv.key > /etc/wireguard/server_pub.key + +Create a WireGuard configuration file `/etc/wireguard/wg0.conf`, where `wg0` is the name of the network interface: + + [Interface] + Address = 172.16.0.1/24 + ListenPort = 51820 + PrivateKey = (server's private key goes here) + # Firewall rules + PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + + [Peer] + # Client #1 details + PublicKey = (client's public key goes here) + # Traffic to route to this client + AllowedIPs = 172.16.0.2/32 + +Paste the server's private key and client's public key on their respective +lines, each being around 45 characters with an equal sign at the end. + +#### Note on extra peers + +In our example, the subnet could recognize up to 254 other peers. Add the new +peer's info below the first peer and update the `AllowedIPS` line to the next virtual +ip. Don't change the `32`: this ensures everyone's tunnel is isolated. +Use this optionally for extra devices or for friends. + +Enable and start the WireGuard service: + + systemctl enable --now wg-quick@wg0.service + +Change `wg0` to match the name of the config file if you called it something different. + +### Back to the Client + +Create another WireGuard configuration file in `/etc/wireguard/myvpn.conf`: + + [Interface] + Address = 172.16.0.2/24 + PrivateKey = (client's private key goes here) + # Set to your desired DNS server + # DNS = 9.9.9.9 + + [Peer] + PublicKey = (server's public key goes here) + # Endpoint (server) can be a domain name or IP address + Endpoint = (server's IP address goes here):51820 + # Traffic to route to server + AllowedIPs = 0.0.0.0/0, ::/0 + +Fill in your information where needed. Remember to use your server's public ip address, not the wireguard one. + +Start WireGuard: + + sudo wg-quick up myvpn + +If you cannot ping `172.16.0.1` or reach the Internet, and have meticulously followed this guide so far, +there's a good chance you're behind a corporate firewall. Read on. + +## WebSocket Tunnel + +#### Note on TLS + +If your server hosts a website with https, you won't be able to use port 443 to +obfuscate your WireGuard packets as TLS traffic. You may use some other innocuous +port, but there's no guarantee you'll punch through the picky firewall. + +### On the Server + +Download and install wstunnel: + + wget https://github.com/erebe/wstunnel/releases/download/v4.0/wstunnel-x64-linux + mv wstunnel-x64-linux /usr/local/bin/wstunnel + chmod uo+x /usr/local/bin/wstunnel + setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/wstunnel + +Make a new systemd service config file, `/etc/systemd/system/wstunnel.service`: + + [Unit] + Description=Tunnel WireGuard UDP over websocket + After=network.target + + [Service] + Type=simple + User=nobody + ExecStart=/usr/local/bin/wstunnel -v --server wss://0.0.0.0:443 --restrictTo=127.0.0.1:51820 + Restart=no + + [Install] + WantedBy=multi-user.target + +Enable and start wstunnel: + + systemctl enable --now wstunnel + +### On the Client + +Download and install wstunnel and a helper script: + + wget https://github.com/erebe/wstunnel/releases/download/v4.0/wstunnel-x64-linux + sudo mv wstunnel-x64-linux /usr/local/bin/wstunnel + sudo chmod +x /usr/local/bin/wstunnel + wget https://raw.githubusercontent.com/jnsgruk/wireguard-over-wss/master/wstunnel.sh + sudo mv wstunnel.sh /etc/wireguard/wstunnel.sh + sudo chmod +x /etc/wireguard/wstunnel.sh + +Create the wstunnel configuration file, `/etc/wireguard/myvpn.wstunnel`: + + REMOTE_HOST=(server's IP address goes here) + REMOTE_PORT=51820 + # Use the following line if you're connecting to your VPN server using a domain name. + # UPDATE_HOSTS='/etc/hosts' + +Edit `/etc/wireguard/myvpn.conf`. Change the `Endpoint` line to `127.0.0.1:51820` and add these four lines to the `[Interface]` section: + + Table = off + PreUp = source /etc/wireguard/wstunnel.sh && pre_up %i + PostUp = source /etc/wireguard/wstunnel.sh && post_up %i + PostDown = source /etc/wireguard/wstunnel.sh && post_down %i + +Start WireGuard again: + + sudo wg-quick up myvpn + +To disconnect, type `down` instead of `up`. And just like that, you now host a WireGuard VPN server! diff --git a/content/yarr.md b/content/yarr.md new file mode 100644 index 0000000..ecbf3d5 --- /dev/null +++ b/content/yarr.md @@ -0,0 +1,103 @@ +--- +title: "Yarr" +date: 2022-07-01 +icon: "yarr.svg" +tags: ["service"] +short_desc: "A self-hosted, web-based feed aggregator" +--- + +[Yarr](https://github.com/nkanaev/yarr) (yet another rss reader) is a web-based feed aggregator which can be used both as a desktop application and a personal self-hosted server. + +It is written in Go with the frontend in Vue.js. The storage is backed by SQLite. + +## Installing Yarr + +Firstly, we have to download yarr binary from github on our system + +```sh +wget https://github.com/nkanaev/yarr/releases/download/v2.3/yarr-v2.3-linux64.zip +``` + +Unzip the archive + +```sh +unzip -x yarr-v2.3-linux64.zip +``` + +Move the binary to your bin folder + +```sh +mv yarr /usr/local/bin/yarr +``` + +## Configuration + +Now we need to create a `auth.conf` file that include user and password to create a local yarr account. +I personnaly store this file in a directory called yarr in `~/.config` folder, but you can place the file wherever you want. + +```sh +mkdir ~/.config/yarr +echo 'sich:password' > ~/.config/yarr/auth.conf +``` + +## Creating a service + +Create a new file /etc/systemd/system/yarr.service and add the following: + +```systemd +[Unit] +Description=Yarr + +[Service] +Environment=HOME=/home/sich +ExecStart=/usr/bin/env yarr -addr 0.0.0.0:7070 -auth-file=/home/sich/.config/yarr/auth.conf -db=/home/sich/.config/yarr/feed.sql -log-file=/home/sich/.config/yarr/access.log +Restart=on-failure + +[Install] +WantedBy=multi-user.target +``` + +After creating the config, load, start and enable the service with the following commands. + +```sh +systemctl daemon-reload +systemctl enable --now yarr +``` + +## Nginx configuration + +Create an Nginx configuration file for Yarr, say /etc/nginx/sites-available/yarr and add the content below: + +```nginx +server { + listen 80 ; + listen [::]:80 ; + + server_name rss.example.org ; + + location / { + proxy_pass http://localhost:7070/; + } +} +``` + +Now let's enable the Nginx Yarr site and reload Nginx to make it active. + +```sh +ln -s /etc/nginx/sites-available/yarr /etc/nginx/sites-enabled +systemctl reload nginx +``` + +### Encryption + +You can encrypt your yarr subdomain as well. Let's do that with certbot: + +```sh +certbot --nginx -d rss.example.org +``` + +Now you can go to rss.example.org, login and start to add your feeds! + +## Contribution + +Author: Jppaled -- [jppaled.xyz](https://jppaled.xyz) \-- XMR: `86bVp8bcx1F3y3NsfuTRs6D7FfnDyLomV7dLJmus2YMiY9Aat6W5m8JGwuvH39HKrq3immS7noKq8HeW4gb4BFbyLoz5WSZ`{.crypto} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..6a1b6ff --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="{{ .Site.Language }}"> +<head> + <title>{{ if not .IsHome }}{{ .Title | title }} | {{ end }}{{ .Site.Title }}</title> + <link rel="canonical" href="{{ .Site.BaseURL }}"> + <link rel='alternate' type='application/rss+xml' title="{{ .Site.Title }} RSS" href='/index.xml'> + <link rel='stylesheet' type='text/css' href='/style.css'> + {{ with .Site.Params.favicon }}<link rel="icon" href="{{ . }}"> + {{ end -}} + <meta name="description" content="{{ with .Params.description }}{{ . }}{{ else }}{{ .Summary }}{{ end }}"> + {{ if isset .Params "tags" }}<meta name="keywords" content="{{ with .Params.tags }}{{ delimit . ", " }}{{ end }}"> + {{ end -}} + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="robots" content="index, follow"> + <meta charset="utf-8"> +</head> +<body> +{{ if .Site.Menus.main }}{{ partial "nav.html" . }}{{ end -}} +<main> +<header><h1>{{ with .Params.icon }}<img src="/pix/{{ . }}" class=titleicon>{{ end }}{{ .Title }}</h1></header> +<article>{{ with .Params.img }}<img src="/pix/{{ . }}" class=titleimg>{{ end }} +{{ block "main" . -}} +{{ .Content }} +{{- end -}} +</article> +{{- if in .Params.tags "basic" -}} +{{ with .NextInSection }} +<a class=next href="{{ .RelPermalink }}">Next: {{ .Title }}</a> +{{- end }} +{{- with .PrevInSection }} +<span class=prev>Or Previous: <a href="{{ .RelPermalink }}">{{ .Title }}</a></span> +{{- end -}} +{{- end }} +{{ if in .Params.tags "mail" -}} +{{ with .NextInSection -}} +<a class=next href="{{ .RelPermalink }}">Next: {{ .Title }}</a> +{{- end -}} +{{- with .PrevInSection }} +<span class=prev>Or Previous: <a href="{{ .RelPermalink }}">{{ .Title }}</a></span> +{{- end -}} +{{- end }} +</main> +{{ block "footer" . -}} +<footer> + <a href="{{ .Site.BaseURL }}">{{ .Site.BaseURL }}</a> + {{- if .Param "showrss" }}<br><br><a href="/index.xml"><img src="/rss.svg" style="max-height:1.5em" alt="RSS Feed" title="Subscribe via RSS for updates."></a>{{ end }} +</footer> +{{- end }} +</body> +</html> diff --git a/layouts/shortcodes/basic.html b/layouts/shortcodes/basic.html new file mode 100644 index 0000000..b2df0d9 --- /dev/null +++ b/layouts/shortcodes/basic.html @@ -0,0 +1,8 @@ +<ol class=ll> +{{range.Site.RegularPages.ByDate}}{{ if in .Params.tags "basic" }}<li> +<a href="{{.Permalink}}"> +{{ with .Params.icon }}<img src="pix/{{ . }}">{{ end }} +<span class=title>{{.Title}}</span> +{{ with .Params.short_desc }}<span class=desc>{{ . }}</span>{{ end }}</a><span style="display:none">{{.Params.Tags}}</span> +</li>{{ end }}{{ end }} +</ol> diff --git a/layouts/shortcodes/hl.html b/layouts/shortcodes/hl.html new file mode 100644 index 0000000..de10914 --- /dev/null +++ b/layouts/shortcodes/hl.html @@ -0,0 +1 @@ +<mark>{{ .Inner }}</mark>
\ No newline at end of file diff --git a/layouts/shortcodes/mail.html b/layouts/shortcodes/mail.html new file mode 100644 index 0000000..53cc3b9 --- /dev/null +++ b/layouts/shortcodes/mail.html @@ -0,0 +1,9 @@ +<ol class=ll> +{{range.Site.RegularPages.ByWeight.Reverse}}{{ if in .Params.tags "mail" }}<li> +<a href="{{.Permalink}}"> +{{ with .Params.icon }}<img src="pix/{{ . }}">{{ end }} +<span class=title>{{.Title}}</span> +{{ with .Params.short_desc }}<span class=desc>{{ . }}</span>{{ end }}</a><span style="display:none">{{.Params.Tags}}</span> +</li>{{ end }}{{ end }} +</ol> + diff --git a/layouts/shortcodes/maintain.html b/layouts/shortcodes/maintain.html new file mode 100644 index 0000000..a864eab --- /dev/null +++ b/layouts/shortcodes/maintain.html @@ -0,0 +1,4 @@ +<ul class=ll> +{{range.Site.RegularPages.ByTitle}}{{ if in .Params.tags "server" }}<li><a href="{{.Permalink}}">{{ with .Params.icon }}<img src="pix/{{ . }}">{{ end }}<span class=title>{{.Title}}</span>{{ with .Params.short_desc }}<span class=desc>{{ . }}</span>{{ end }}</a><span class=tags>{{.Params.Tags}}</span></li> +{{ end }}{{ end }} +</ul> diff --git a/layouts/shortcodes/services.html b/layouts/shortcodes/services.html new file mode 100644 index 0000000..877140d --- /dev/null +++ b/layouts/shortcodes/services.html @@ -0,0 +1,4 @@ +<ul id=servicelist> +{{range.Site.RegularPages.ByTitle}}{{ if in .Params.tags "service" }}<li><a href="{{.Permalink}}">{{ with .Params.icon }}<img src="pix/{{ . }}">{{ end }}<span class=title>{{.Title}}</span>{{ with .Params.short_desc }}<span class=desc>{{ . }}</span>{{ end }}</a><span class=tags>{{.Params.Tags}}</span></li> +{{ end }}{{ end }} +</ul> diff --git a/static/favicon.ico b/static/favicon.ico Binary files differnew file mode 100644 index 0000000..d8f549d --- /dev/null +++ b/static/favicon.ico diff --git a/static/pix/alps.webp b/static/pix/alps.webp Binary files differnew file mode 100644 index 0000000..23f1790 --- /dev/null +++ b/static/pix/alps.webp diff --git a/static/pix/auth.svg b/static/pix/auth.svg new file mode 100644 index 0000000..5b17192 --- /dev/null +++ b/static/pix/auth.svg @@ -0,0 +1,1461 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + version="1.1" + id="svg187" + width="327.67999" + height="184.32001" + viewBox="0 0 327.67999 184.32001" + sodipodi:docname="auth.svg" + inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs191" /> + <sodipodi:namedview + id="namedview189" + pagecolor="#505050" + bordercolor="#eeeeee" + borderopacity="1" + inkscape:pageshadow="0" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="3.6468507" + inkscape:cx="163.84" + inkscape:cy="92.271395" + inkscape:window-width="1920" + inkscape:window-height="1024" + inkscape:window-x="2109" + inkscape:window-y="28" + inkscape:window-maximized="1" + inkscape:current-layer="g193" /> + <g + inkscape:groupmode="layer" + inkscape:label="Image" + id="g193"> + <image + width="327.67999" + height="184.32001" + preserveAspectRatio="none" + xlink:href="data:image/png;base64,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 +sFhvj/djzgTpYpFBAgqMucALmmA32dIsQzjOS8V4uy5IMyQ1XGraLYm/r8D9tAQY5IDX9HekT4Fn +TIy2OahK5B0IB1glikZbyjaL/DpfM/gANZz8PWQrvRz42mT4WAAIfM7TjentZ+qu5NTeEz6GUqJt +0Vmrf+QhwtocssFPbVhZxccgrXDfCb+KTfKchc1HxyXN97kbNA7MSaskoH1qFwVQxk0PB21h3Cgq +iQTcAU7Gy+I0zCgSUn0EVN2Q4jLalYVl2OrAQOLmhcvFwqFcHC5zC9UONlpOetVdgFH4bL07OHAm +YnAd7DKisg1ZtYhKanLhmAACvXWzwWmNp8jmMgfd4rP4Eb9wzL9zT9P9TTdF/68PRG8O99/i0SwR +BaCXfAAAAYRpQ0NQSUNDIHByb2ZpbGUAAHicfZE9SMNAHMVfU7UilQ52EHXIUJ0s+IU4ahWKUKHU +Cq06mFz6BU0akhQXR8G14ODHYtXBxVlXB1dBEPwAcXNzUnSREv+XFFrEeHDcj3f3HnfvAKFeZqrZ +MQaommWk4jExk10VA6/owiBCGEdQYqY+l0wm4Dm+7uHj612UZ3mf+3P0KjmTAT6ReJbphkW8QTy9 +aemc94nDrCgpxOfEowZdkPiR67LLb5wLDgs8M2ykU/PEYWKx0MZyG7OioRJPEUcUVaN8IeOywnmL +s1qusuY9+QuDOW1lmes0hxDHIpaQhAgZVZRQhoUorRopJlK0H/PwDzj+JLlkcpXAyLGAClRIjh/8 +D353a+YnJ9ykYAzofLHtj2EgsAs0arb9fWzbjRPA/wxcaS1/pQ7MfJJea2mRIyC0DVxctzR5D7jc +AfqfdMmQHMlPU8jngfcz+qYs0HcL9Ky5vTX3cfoApKmrxA1wcAiMFCh73ePd3e29/Xum2d8PfU9y +q543VLoAAA3naVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIg +aWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2Jl +Om5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxu +czpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxy +ZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFk +b2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29t +L3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpzdFJlZj0iaHR0cDovL25z +LmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgIHhtbG5zOmRjPSJodHRw +Oi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgIHhtbG5zOkdJTVA9Imh0dHA6Ly93d3cu +Z2ltcC5vcmcveG1wLyIKICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8x +LjAvIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICB4bXBN +TTpEb2N1bWVudElEPSJ4bXAuZGlkOjUzNjJCMUJDNDE2NDExRTlBMzVERjdBRTQ5RkY2NEE3Igog +ICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM4Y2ExNWM4LWFkYWMtNGMwZC04MWQzLWQ2NGJi +OGQwMjU5MyIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjdjNjRlNWEwLWU2 +NDctNGJjZC1hMmE3LWQ4MTRhNzMxODk5YiIKICAgZGM6Rm9ybWF0PSJpbWFnZS9wbmciCiAgIEdJ +TVA6QVBJPSIyLjAiCiAgIEdJTVA6UGxhdGZvcm09IkxpbnV4IgogICBHSU1QOlRpbWVTdGFtcD0i +MTYyNDgwOTE0NDA1OTY1OSIKICAgR0lNUDpWZXJzaW9uPSIyLjEwLjI0IgogICB0aWZmOk9yaWVu +dGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+CiAgIDx4bXBNTTpIaXN0 +b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVk +IgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlk +OmExZGRlYWExLWQyNTYtNGMxNS04OTRiLTFiYWI2ZjA2NjFhZSIKICAgICAgc3RFdnQ6c29mdHdh +cmVBZ2VudD0iR2ltcCAyLjEwIChMaW51eCkiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMDYtMjdU +MTE6NTI6MjQtMDQ6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogICA8 +eG1wTU06RGVyaXZlZEZyb20KICAgIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NTM2MkIxQkE0 +MTY0MTFFOUEzNURGN0FFNDlGRjY0QTciCiAgICBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjUz +NjJCMUI5NDE2NDExRTlBMzVERjdBRTQ5RkY2NEE3Ii8+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8 +L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg +ICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz53BIxFAAAABmJLR0QA/wD/AP+g +vaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5QYbDzQXsaA0ogAAIABJREFUeNrs3emz +Zdd53/dnredZ+5xzhx7R3RgaU2OeSBAaSU2UKcuUrJJsJ7ZTeeHETiWVVMVVqbzOi/wPdiVVrqQq +KdkllezYGijKFCVxFgmCE4iBBBpjAyDQaPTc996z95ry4nY3Ly7OePv2/P1UnboHB7fvcLr32s/z +22utLQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHC5Od4CAAAAYHv8y3/9wsz19b/6 +nx+rvGMACAAAAACAG6zhJwwAQAAAAAAA3IRNP2EAAAIAgCIBwHWCIh3gnM4YA4AAAKAoAEAwAIBz +PGMKAAIAgIIAAGEAAM7zjCcACAAACgIABAEAOM8zngAgAAAoCAAQBADgPM94AoAAAKAoAEDRDuAm +OsczpgAgAAAoDABQsAO4ic7vjCsACAAACgMAFOsAbqJzPGMLAAIAgOIAAIU6wLn9Jjq3M74AIAAA +KBAAUKQDnNcZXwAQAACg+QdAkQ5wTmeMAUAAAFAoAAAFOsD5/FLq7Kt6nDPOAAQAAGj+ARACAJzP +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 +ARAAAEfggcz1A+CjbO5pGoCTW3dw/QKggQGObggAAEcKzQNw/OoPrlsABAAAIQAA0EQAJ7AW4VoF +QAAAEAIAAM0/AAAgAAAIAQCA5h8AABAAAIQAAGj+AQAAZjD8EwAAAAAAcPIxOooTj1kAAE4qRv8B +AAABAEAIAIDmHwAAgAAAhAAAQPMPAAAIAABCAACg+QcAAAQAACEAAND8AwAAAgCAIAAAaPwBAAAB +AEAQAAA0/gAAgAAAIAwAQNNP0w8AAAgAgI8CoQAAmn0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwN79fzWOelPGLIibAAAAAElF +TkSuQmCC +" + id="image195" /> + </g> +</svg> diff --git a/static/pix/bat.svg b/static/pix/bat.svg new file mode 100644 index 0000000..2154658 --- /dev/null +++ b/static/pix/bat.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 140.9 136.3" style="enable-background:new 0 0 140.9 136.3;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.3;enable-background:new ;} + .st1{fill:#662D91;} + .st2{fill:#9E1F63;} + .st3{fill:#FF5000;} + .st4{fill:#FFFFFF;stroke:#FF5000;stroke-width:0.83;stroke-miterlimit:10;} +</style> +<title>BAT_icon</title> +<g id="Layer_2"> + <g id="Layer_1-2"> + <polygon class="st0" points="97,132.6 140.9,133 64.2,0 1.2,110.2 "/> + <polygon class="st1" points="127.3,109.8 64.3,73.7 1.2,110.2 "/> + <polygon class="st2" points="64.2,0 63.8,73.7 127.3,109.8 "/> + <polygon class="st3" points="1.2,110.2 64,74.3 64.2,0 "/> + <polygon class="st4" points="63.8,44.8 38.4,88.5 89.9,88.5 "/> + </g> +</g> +</svg> diff --git a/static/pix/bitcoin-01.png b/static/pix/bitcoin-01.png Binary files differnew file mode 100644 index 0000000..8f38d0e --- /dev/null +++ b/static/pix/bitcoin-01.png diff --git a/static/pix/bitcoin-02.png b/static/pix/bitcoin-02.png Binary files differnew file mode 100644 index 0000000..a566a18 --- /dev/null +++ b/static/pix/bitcoin-02.png diff --git a/static/pix/bitcoin-03.png b/static/pix/bitcoin-03.png Binary files differnew file mode 100644 index 0000000..dd02d8d --- /dev/null +++ b/static/pix/bitcoin-03.png diff --git a/static/pix/bitcoin-04.png b/static/pix/bitcoin-04.png Binary files differnew file mode 100644 index 0000000..104f179 --- /dev/null +++ b/static/pix/bitcoin-04.png diff --git a/static/pix/btc.png b/static/pix/btc.png Binary files differnew file mode 100644 index 0000000..bbe842c --- /dev/null +++ b/static/pix/btc.png diff --git a/static/pix/btc.svg b/static/pix/btc.svg new file mode 100644 index 0000000..b3fd9e3 --- /dev/null +++ b/static/pix/btc.svg @@ -0,0 +1,7 @@ +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> +<g transform="translate(0.00630876,-0.00301984)"> +<path fill="#f7931a" d="m63.033,39.744c-4.274,17.143-21.637,27.576-38.782,23.301-17.138-4.274-27.571-21.638-23.295-38.78,4.272-17.145,21.635-27.579,38.775-23.305,17.144,4.274,27.576,21.64,23.302,38.784z"/> +<path fill="#FFF" d="m46.103,27.444c0.637-4.258-2.605-6.547-7.038-8.074l1.438-5.768-3.511-0.875-1.4,5.616c-0.923-0.23-1.871-0.447-2.813-0.662l1.41-5.653-3.509-0.875-1.439,5.766c-0.764-0.174-1.514-0.346-2.242-0.527l0.004-0.018-4.842-1.209-0.934,3.75s2.605,0.597,2.55,0.634c1.422,0.355,1.679,1.296,1.636,2.042l-1.638,6.571c0.098,0.025,0.225,0.061,0.365,0.117-0.117-0.029-0.242-0.061-0.371-0.092l-2.296,9.205c-0.174,0.432-0.615,1.08-1.609,0.834,0.035,0.051-2.552-0.637-2.552-0.637l-1.743,4.019,4.569,1.139c0.85,0.213,1.683,0.436,2.503,0.646l-1.453,5.834,3.507,0.875,1.439-5.772c0.958,0.26,1.888,0.5,2.798,0.726l-1.434,5.745,3.511,0.875,1.453-5.823c5.987,1.133,10.489,0.676,12.384-4.739,1.527-4.36-0.076-6.875-3.226-8.515,2.294-0.529,4.022-2.038,4.483-5.155zm-8.022,11.249c-1.085,4.36-8.426,2.003-10.806,1.412l1.928-7.729c2.38,0.594,10.012,1.77,8.878,6.317zm1.086-11.312c-0.99,3.966-7.1,1.951-9.082,1.457l1.748-7.01c1.982,0.494,8.365,1.416,7.334,5.553z"/> +</g> +</svg>
\ No newline at end of file diff --git a/static/pix/btcpay.svg b/static/pix/btcpay.svg new file mode 100644 index 0000000..bb9f410 --- /dev/null +++ b/static/pix/btcpay.svg @@ -0,0 +1 @@ +<svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105.46 188.47"><defs><style>.cls-1{fill:#cedc21;}.cls-2{fill:#51b13e;}.cls-3{fill:#1e7a44;}.cls-4{fill:#fff;}</style></defs><title>btcpay</title><path class="cls-1" d="M117.24,247.32a11.06,11.06,0,0,1-11-11.06V69.91a11.06,11.06,0,1,1,22.11,0V236.26A11.06,11.06,0,0,1,117.24,247.32Z" transform="translate(-106.19 -58.85)"/><path class="cls-2" d="M117.25,247.32a11.06,11.06,0,0,1-4.75-21l66.66-31.64L110.69,144.2a11.05,11.05,0,1,1,13.11-17.8l83.35,61.41a11,11,0,0,1-1.82,18.88L122,246.25A10.94,10.94,0,0,1,117.25,247.32Z" transform="translate(-106.19 -58.85)"/><path class="cls-1" d="M117.25,181.93a11.05,11.05,0,0,1-6.56-20l68.47-50.45L112.5,79.89a11.05,11.05,0,0,1,9.48-20l83.35,39.56a11.05,11.05,0,0,1,1.82,18.89L123.8,179.78A11,11,0,0,1,117.25,181.93Z" transform="translate(-106.19 -58.85)"/><polygon class="cls-3" points="22.11 70.86 22.11 117.61 53.82 94.25 22.11 70.86"/><rect class="cls-4" y="51.26" width="22.11" height="53.89"/><path class="cls-1" d="M128.3,69.91a11.06,11.06,0,1,0-22.11,0V209H128.3Z" transform="translate(-106.19 -58.85)"/></svg>
\ No newline at end of file diff --git a/static/pix/calibre.png b/static/pix/calibre.png Binary files differnew file mode 100644 index 0000000..81adc85 --- /dev/null +++ b/static/pix/calibre.png diff --git a/static/pix/calibre/calibre-1.png b/static/pix/calibre/calibre-1.png Binary files differnew file mode 100644 index 0000000..cf767e0 --- /dev/null +++ b/static/pix/calibre/calibre-1.png diff --git a/static/pix/calibre/calibre-2.png b/static/pix/calibre/calibre-2.png Binary files differnew file mode 100644 index 0000000..e0c76ba --- /dev/null +++ b/static/pix/calibre/calibre-2.png diff --git a/static/pix/certbot-01.png b/static/pix/certbot-01.png Binary files differnew file mode 100644 index 0000000..37d81f8 --- /dev/null +++ b/static/pix/certbot-01.png diff --git a/static/pix/certbot-02.png b/static/pix/certbot-02.png Binary files differnew file mode 100644 index 0000000..24905f8 --- /dev/null +++ b/static/pix/certbot-02.png diff --git a/static/pix/certbot-03.png b/static/pix/certbot-03.png Binary files differnew file mode 100644 index 0000000..1a60fe9 --- /dev/null +++ b/static/pix/certbot-03.png diff --git a/static/pix/cgit.svg b/static/pix/cgit.svg new file mode 100644 index 0000000..72eafa6 --- /dev/null +++ b/static/pix/cgit.svg @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" + "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> + +<svg xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 96 64"> + <path id="cgit" + fill="#9e1212" + d="M 44.00,3.00 + C 44.00,3.00 44.00,8.00 44.00,8.00 + 44.00,8.00 49.00,8.00 49.00,8.00 + 49.00,8.00 49.00,3.00 49.00,3.00 + 49.00,3.00 44.00,3.00 44.00,3.00 Z + M 60.00,9.00 + C 60.00,9.00 60.00,16.00 60.00,16.00 + 60.00,16.00 56.00,16.00 56.00,16.00 + 56.00,16.00 56.02,19.98 56.02,19.98 + 56.02,19.98 59.98,20.00 59.98,20.00 + 59.98,20.00 60.00,37.00 60.00,37.00 + 60.00,39.99 59.69,44.16 61.74,46.57 + 64.65,50.00 76.35,50.00 79.26,46.57 + 81.32,44.16 80.99,40.00 81.00,37.00 + 81.00,37.00 76.06,37.06 76.06,37.06 + 76.24,39.83 76.03,41.32 75.03,42.59 + 73.56,44.38 66.99,45.07 65.50,41.50 + 64.15,38.26 64.96,24.11 64.96,19.98 + 64.96,19.98 81.09,20.00 81.09,20.00 + 81.09,20.00 81.00,16.00 81.00,16.00 + 81.00,16.00 65.00,16.00 65.00,16.00 + 65.00,16.00 65.00,9.00 65.00,9.00 + 65.00,9.00 60.00,9.00 60.00,9.00 Z + M 29.00,47.09 + C 29.25,50.45 28.52,54.06 26.65,55.52 + 20.83,58.74 10.73,56.80 12.00,51.09 + 12.00,51.09 7.00,51.00 7.00,51.00 + 7.17,53.91 7.21,56.35 9.43,58.46 + 13.06,62.20 27.71,62.00 31.35,58.46 + 35.19,54.51 34.00,42.41 34.00,37.00 + 31.56,36.97 29.09,37.03 29.04,37.02 + 28.58,39.20 31.61,44.05 18.12,44.25 + 11.60,44.36 10.78,40.13 11.00,31.26 + 10.87,24.96 11.04,25.57 11.26,24.48 + 11.57,22.83 12.52,19.83 19.30,19.87 + 24.22,19.57 30.09,21.65 29.03,26.92 + 30.65,27.09 32.70,26.89 34.00,27.00 + 33.93,24.32 34.05,21.62 32.26,19.39 + 28.04,14.77 12.76,14.65 9.23,18.43 + 7.78,19.72 6.94,21.15 6.58,23.00 + 5.65,25.83 5.70,40.36 6.58,42.98 + 7.44,44.76 8.54,46.17 10.11,47.26 + 14.03,49.99 27.17,49.00 29.00,47.09 Z + M 44.00,16.00 + C 44.00,16.00 44.00,49.00 44.00,49.00 + 44.00,49.00 49.00,49.00 49.00,49.00 + 49.00,49.00 49.00,16.00 49.00,16.00 + 49.00,16.00 44.00,16.00 44.00,16.00 Z + M 77.25,34.75M 18.25,44.69M 37.81,44.81M 32.26,50.57M 30.26,21.52M 29.09,20.70M 74.84,43.19" /> +</svg> diff --git a/static/pix/chad.gif b/static/pix/chad.gif Binary files differnew file mode 100644 index 0000000..98b8904 --- /dev/null +++ b/static/pix/chad.gif diff --git a/static/pix/devault.jpg b/static/pix/devault.jpg Binary files differnew file mode 100644 index 0000000..a3dc88a --- /dev/null +++ b/static/pix/devault.jpg diff --git a/static/pix/dkim-01.png b/static/pix/dkim-01.png Binary files differnew file mode 100644 index 0000000..ab8a9a4 --- /dev/null +++ b/static/pix/dkim-01.png diff --git a/static/pix/dns-epik.png b/static/pix/dns-epik.png Binary files differnew file mode 100644 index 0000000..0bbc8c5 --- /dev/null +++ b/static/pix/dns-epik.png diff --git a/static/pix/dns-ipv4-done.png b/static/pix/dns-ipv4-done.png Binary files differnew file mode 100644 index 0000000..1195f06 --- /dev/null +++ b/static/pix/dns-ipv4-done.png diff --git a/static/pix/dns-ipv4.png b/static/pix/dns-ipv4.png Binary files differnew file mode 100644 index 0000000..d9c14cd --- /dev/null +++ b/static/pix/dns-ipv4.png diff --git a/static/pix/dns-ipv6-done.png b/static/pix/dns-ipv6-done.png Binary files differnew file mode 100644 index 0000000..0559575 --- /dev/null +++ b/static/pix/dns-ipv6-done.png diff --git a/static/pix/dns-ipv6.png b/static/pix/dns-ipv6.png Binary files differnew file mode 100644 index 0000000..8fffd6a --- /dev/null +++ b/static/pix/dns-ipv6.png diff --git a/static/pix/dns-ping.png b/static/pix/dns-ping.png Binary files differnew file mode 100644 index 0000000..f900774 --- /dev/null +++ b/static/pix/dns-ping.png diff --git a/static/pix/dns-vultr.png b/static/pix/dns-vultr.png Binary files differnew file mode 100644 index 0000000..9db0be7 --- /dev/null +++ b/static/pix/dns-vultr.png diff --git a/static/pix/dnsmasq.svg b/static/pix/dnsmasq.svg new file mode 100644 index 0000000..7c1732e --- /dev/null +++ b/static/pix/dnsmasq.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" width="83.756851" height="46.067505" viewBox="0 0 83.756851 46.067505" enable-background="new 0 0 72.833 46.667" xml:space="preserve" id="svg2" inkscape:version="0.47 r22583" sodipodi:docname="dnsmasq_icon.2010_10_21_08_54_27.0.svg"><metadata id="metadata27"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><defs id="defs25"><inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 23.3335 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="72.833 : 23.3335 : 1" inkscape:persp3d-origin="36.4165 : 15.555667 : 1" id="perspective4857"/> + <filter id="filter3802" inkscape:label="filter1" color-interpolation-filters="sRGB"/><linearGradient inkscape:collect="always" xlink:href="#SVGID_3_" id="linearGradient4929" gradientUnits="userSpaceOnUse" x1="30.564501" y1="-8.8144999" x2="32.937" y2="32.715599"/> + <linearGradient inkscape:collect="always" xlink:href="#SVGID_3_" id="linearGradient5798" gradientUnits="userSpaceOnUse" x1="30.564501" y1="-8.8144999" x2="32.937" y2="32.715599"/><linearGradient inkscape:collect="always" xlink:href="#SVGID_3_" id="linearGradient5812" gradientUnits="userSpaceOnUse" x1="30.564501" y1="-8.8144999" x2="32.937" y2="32.715599"/><filter id="filter6262" inkscape:label="Drop shadow" width="1.5" height="1.5" x="-0.25" y="-0.25" color-interpolation-filters="sRGB"><feGaussianBlur id="feGaussianBlur6264" in="SourceAlpha" stdDeviation="2.500000" result="blur"/><feColorMatrix id="feColorMatrix6266" result="bluralpha" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.500000 0 "/><feOffset id="feOffset6268" in="bluralpha" dx="2.700000" dy="2.600000" result="offsetBlur"/><feMerge id="feMerge6270"><feMergeNode id="feMergeNode6272" in="offsetBlur"/><feMergeNode id="feMergeNode6274" in="SourceGraphic"/></feMerge></filter></defs><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1568" inkscape:window-height="1076" id="namedview23" showgrid="false" inkscape:zoom="1" inkscape:cx="31.966768" inkscape:cy="23.211869" inkscape:window-x="567" inkscape:window-y="328" inkscape:window-maximized="0" inkscape:current-layer="layer1" inkscape:showpageshadow="false" showborder="false"/> +<g inkscape:groupmode="layer" id="layer1" inkscape:label="dnsmasq" style="display:inline" transform="translate(5.2838057,-0.47786591)"><g id="g3790" transform="translate(91.821581,0.57952319)" style="filter:url(#filter6262)"><g transform="translate(-91.018462,1.0687099)" id="g9"> + <path style="fill:#6700ad" inkscape:connector-curvature="0" id="path11" d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z"/> + <path style="fill:none;stroke:#ffb616;stroke-width:1.51689994" inkscape:connector-curvature="0" id="path13" d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z"/> + </g><g transform="translate(-91.018462,1.0687099)" id="Layer_2"> + <linearGradient y2="32.715599" x2="32.937" y1="-8.8144999" x1="30.564501" gradientUnits="userSpaceOnUse" id="SVGID_3_"> + <stop id="stop17" style="stop-color:#FFFFFF;stop-opacity:0.73" offset="0"/> + <stop id="stop19" style="stop-color:#FFFFFF;stop-opacity:0" offset="1"/> + </linearGradient> + <path inkscape:connector-curvature="0" style="fill:url(#linearGradient5812)" id="path21" d="m 54.1,15.361 c -0.924,1.078 -2.782,1.265 -3.857,1.06 C 38,14.083 22.75,12.75 16.027,23.031 14.858,24.819 11.992,25.39 10.293,23.887 8.631,22.417 13.105,15.804 17.646,13.033 22.194,10.252 28.474,8.53 35.41,8.53 c 6.936,0 13.215,1.722 17.756,4.502 0.731,0.442 1.627,1.52 0.934,2.329 z"/> +</g></g></g></svg>
\ No newline at end of file diff --git a/static/pix/dokuwiki.svg b/static/pix/dokuwiki.svg new file mode 100644 index 0000000..e99d8b1 --- /dev/null +++ b/static/pix/dokuwiki.svg @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="128.17094" height="128.03864" id="svg2" sodipodi:version="0.32" inkscape:version="0.48.1 " sodipodi:docname="dokuwiki-logo.svg" version="1.1"> + <title id="title3181">DokuWiki Logo</title> + <defs id="defs4"> + <linearGradient id="linearGradient2624"> + <stop style="stop-color:#3a9030;stop-opacity:0.83673471;" offset="0" id="stop2626"/> + <stop style="stop-color:#3d9c32;stop-opacity:0.79591835;" offset="1" id="stop2628"/> + </linearGradient> + <linearGradient id="linearGradient2612"> + <stop style="stop-color:#25901b;stop-opacity:0.83673471;" offset="0" id="stop2614"/> + <stop style="stop-color:#25901b;stop-opacity:0.37755102;" offset="1" id="stop2616"/> + </linearGradient> + <linearGradient id="linearGradient2600"> + <stop style="stop-color:#e32525;stop-opacity:0.81632656;" offset="0" id="stop2602"/> + <stop style="stop-color:#e32525;stop-opacity:0.5714286;" offset="1" id="stop2604"/> + </linearGradient> + <marker inkscape:stockid="TriangleOutL" orient="auto" refY="0" refX="0" id="TriangleOutL" style="overflow:visible"> + <path id="path2488" d="m 5.77,0 -8.65,5 0,-10 8.65,5 z" style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" transform="scale(0.8,0.8)" inkscape:connector-curvature="0"/> + </marker> + <marker inkscape:stockid="Arrow2Lstart" orient="auto" refY="0" refX="0" id="Arrow2Lstart" style="overflow:visible"> + <path id="path2571" style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" transform="matrix(1.1,0,0,1.1,-5.5,0)" inkscape:connector-curvature="0"/> + </marker> + <linearGradient id="linearGradient2408"> + <stop id="stop2410" offset="0" style="stop-color:#000000;stop-opacity:0.17346939;"/> + <stop id="stop2412" offset="1" style="stop-color:#c7cec2;stop-opacity:0;"/> + </linearGradient> + <linearGradient id="linearGradient2389"> + <stop style="stop-color:#000000;stop-opacity:0.17346939;" offset="0" id="stop2391"/> + <stop style="stop-color:#c7cec2;stop-opacity:0;" offset="1" id="stop2393"/> + </linearGradient> + <linearGradient id="linearGradient2370"> + <stop style="stop-color:#fbfaf9;stop-opacity:1;" offset="0" id="stop2372"/> + <stop style="stop-color:#e9dac7;stop-opacity:1;" offset="1" id="stop2374"/> + </linearGradient> + <linearGradient id="linearGradient2364"> + <stop id="stop2366" offset="0" style="stop-color:#fbf6f0;stop-opacity:1;"/> + <stop id="stop2368" offset="1" style="stop-color:#e9dac7;stop-opacity:1;"/> + </linearGradient> + <linearGradient id="linearGradient2348"> + <stop style="stop-color:#fbf6f0;stop-opacity:1;" offset="0" id="stop2350"/> + <stop style="stop-color:#e9dac7;stop-opacity:1;" offset="1" id="stop2352"/> + </linearGradient> + <linearGradient id="linearGradient2332"> + <stop style="stop-color:#ede1ae;stop-opacity:1;" offset="0" id="stop2334"/> + <stop style="stop-color:#fefdfa;stop-opacity:1;" offset="1" id="stop2336"/> + </linearGradient> + <linearGradient id="linearGradient2249"> + <stop style="stop-color:#00a423;stop-opacity:1;" offset="0" id="stop2251"/> + <stop style="stop-color:#00b427;stop-opacity:1;" offset="1" id="stop2253"/> + </linearGradient> + <linearGradient id="linearGradient2229"> + <stop id="stop2231" offset="0" style="stop-color:#00b62b;stop-opacity:1;"/> + <stop id="stop2233" offset="1" style="stop-color:#a1d784;stop-opacity:1;"/> + </linearGradient> + <linearGradient id="linearGradient2213"> + <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop2215"/> + <stop style="stop-color:#000000;stop-opacity:0;" offset="1" id="stop2217"/> + </linearGradient> + <linearGradient id="linearGradient2360"> + <stop style="stop-color:#d69c00;stop-opacity:1;" offset="0" id="stop2362"/> + <stop style="stop-color:#ffe658;stop-opacity:1;" offset="1" id="stop2364"/> + </linearGradient> + <linearGradient id="linearGradient2352"> + <stop id="stop2354" offset="0" style="stop-color:#ce411e;stop-opacity:1;"/> + <stop id="stop2356" offset="1" style="stop-color:#ecad8d;stop-opacity:1;"/> + </linearGradient> + <linearGradient id="linearGradient2336"> + <stop style="stop-color:#8f2a15;stop-opacity:1;" offset="0" id="stop2338"/> + <stop style="stop-color:#c8381b;stop-opacity:1;" offset="1" id="stop2340"/> + </linearGradient> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2336" id="linearGradient2342" x1="219.21262" y1="189.01556" x2="286.22665" y2="189.01556" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2352" id="linearGradient2350" x1="219.66267" y1="192.73286" x2="277.8761" y2="192.73286" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient2360" id="radialGradient2366" cx="224.41418" cy="212.80016" fx="224.41418" fy="212.80016" r="8.6813803" gradientTransform="matrix(1,0,0,0.984179,0,3.366635)" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2249" id="linearGradient2227" x1="192.03938" y1="262.25757" x2="263.67093" y2="262.25757" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2229" id="linearGradient2247" x1="191.75092" y1="258.91571" x2="255.6561" y2="258.91571" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient2360" id="radialGradient2317" cx="257.41144" cy="274.64203" fx="257.41144" fy="274.64203" r="7.1440549" gradientTransform="matrix(1,0,0,1.631384,0,-173.4045)" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2360" id="linearGradient2325" x1="184.07063" y1="246.35907" x2="201.40646" y2="246.35907" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2332" id="linearGradient2346" x1="162.76369" y1="184.99277" x2="240.84924" y2="289.50323" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2348" id="linearGradient2354" x1="140.15784" y1="303.78967" x2="136.14151" y2="195.87151" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2370" id="linearGradient2362" x1="286.15598" y1="262.28729" x2="185.81258" y2="172.32423" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2389" id="linearGradient2395" x1="213.96568" y1="220.07191" x2="244.79126" y2="265.40363" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2408" id="linearGradient2406" x1="184.30582" y1="241.52789" x2="224.67441" y2="307.52844" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2600" id="linearGradient2606" x1="202.41772" y1="222.05145" x2="206.06017" y2="210.3558" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2612" id="linearGradient2618" x1="248.62152" y1="234.52202" x2="251.64362" y2="213.12164" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2624" id="linearGradient2630" x1="275.71765" y1="251.56442" x2="255.68353" y2="217.94008" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2352" id="linearGradient2640" gradientUnits="userSpaceOnUse" x1="219.66267" y1="192.73286" x2="277.8761" y2="192.73286"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient2336" id="linearGradient2643" gradientUnits="userSpaceOnUse" x1="219.21262" y1="189.01556" x2="286.22665" y2="189.01556"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient2360" id="radialGradient2647" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,0.984179,0,3.366635)" cx="224.41418" cy="212.80016" fx="224.41418" fy="212.80016" r="8.6813803"/> + </defs> + <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.03" inkscape:cx="35.144424" inkscape:cy="83.160427" inkscape:document-units="px" inkscape:current-layer="layer3" inkscape:window-width="1366" inkscape:window-height="716" inkscape:window-x="-8" inkscape:window-y="-8" showguides="true" inkscape:guide-bbox="true" showgrid="false" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" inkscape:window-maximized="1" inkscape:showpageshadow="false" showborder="true" borderlayer="false"/> + <metadata id="metadata7"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title>DokuWiki Logo</dc:title> + <dc:creator> + <cc:Agent> + <dc:title>Esther Brunner</dc:title> + </cc:Agent> + </dc:creator> + <cc:license rdf:resource="http://www.gnu.org/licenses/gpl-2.0.html"/> + </cc:Work> + </rdf:RDF> + </metadata> + <g inkscape:groupmode="layer" id="layer3" inkscape:label="paper" style="display:inline" transform="translate(-158.10602,-158.67323)"> + <g id="g1419" transform="matrix(0.99993322,0,0,0.9959778,0.01483419,0.8957919)"> + <g id="g2376"> + <path transform="matrix(0.989976,-0.141236,0.201069,0.979577,0,0)" style="fill:url(#linearGradient2354);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.7216621px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" d="m 120.21543,196.43769 70.90655,-0.79226 -2.40261,109.05308 -71.71761,0.37344 3.21367,-108.63426 z" id="rect1422" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2362);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" d="m 179.20033,182.08731 79.84173,-19.51687 26.61391,101.72428 -82.50312,21.58684 -23.95252,-103.79425 z" id="rect1425" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0"/> + <path transform="matrix(0.995676,-0.09289891,0.08102261,0.996712,0,0)" style="fill:url(#linearGradient2346);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00418305px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" d="m 159.01353,181.74387 85.58587,0.53396 0,110.47429 -84.53387,-2.5127 -1.052,-108.49555 z" id="rect1419" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0"/> + </g> + <path id="text2382" d="m 167.55116,214.00773 0,-20.1846 5.34962,0 0,2.37403 -2.48145,0 0,15.43654 2.48145,0 0,2.37403 -5.34962,0 m 7.34767,0 0,-20.1846 5.34961,0 0,2.37403 -2.48144,0 0,15.43654 2.48144,0 0,2.37403 -5.34961,0 m 7.36915,-20.1846 5.81153,0 c 1.31054,2e-5 2.30956,0.10028 2.99707,0.30078 0.92382,0.27216 1.71516,0.75555 2.37403,1.4502 0.65884,0.69468 1.16014,1.54689 1.50391,2.55664 0.34373,1.00262 0.51561,2.24155 0.51562,3.71681 -10e-6,1.29623 -0.16115,2.41342 -0.4834,3.35156 -0.39389,1.14584 -0.95607,2.07325 -1.68652,2.78223 -0.55145,0.53711 -1.29624,0.95606 -2.23438,1.25684 -0.70183,0.222 -1.63999,0.33301 -2.81446,0.33301 l -5.9834,0 0,-15.74807 m 3.17969,2.66407 0,10.43067 2.37402,0 c 0.88802,1e-5 1.52897,-0.0501 1.92286,-0.15039 0.51561,-0.1289 0.94172,-0.34732 1.27832,-0.65527 0.34374,-0.30794 0.62304,-0.81282 0.83789,-1.51465 0.21483,-0.70898 0.32226,-1.6722 0.32227,-2.88965 -1e-5,-1.21744 -0.10744,-2.15201 -0.32227,-2.80372 -0.21485,-0.65168 -0.51563,-1.16014 -0.90234,-1.52539 -0.38673,-0.36522 -0.87729,-0.61229 -1.47168,-0.74121 -0.44402,-0.10025 -1.31414,-0.15038 -2.61036,-0.15039 l -1.42871,0 m 14.96388,13.084 -3.75977,-15.74807 3.25489,0 2.37403,10.8174 2.87891,-10.8174 3.78125,0 2.76074,11.00002 2.417,-11.00002 3.20118,0 -3.82423,15.74807 -3.37305,0 -3.13672,-11.77345 -3.12598,11.77345 -3.44825,0 m 22.76272,-15.74807 0,20.1846 -5.34961,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34961,0 m 7.34767,0 0,20.1846 -5.34962,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34962,0" style="font-size:12.0000124px;font-style:normal;font-weight:normal;line-height:125%;fill:#6184a3;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" transform="matrix(0.995433,-0.09546066,0.09546066,0.995433,0,0)" inkscape:connector-curvature="0"/> + <g id="g2632" style="display:inline"> + <path style="fill:url(#linearGradient2606);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker-end:none" d="m 174.75585,201.60224 c -6.04576,2.46667 -10.16789,4.4194 -12.88454,6.35064 -2.71665,1.93124 -3.19257,4.60007 -3.24631,6.26587 -0.0269,0.8329 0.0809,1.77774 0.63189,2.44014 0.55103,0.6624 1.80769,1.87421 2.75794,2.38558 1.90049,1.02274 7.5417,2.42901 10.51899,3.07308 11.90917,2.57627 26.80568,1.68117 26.80568,1.68117 1.69307,1.2452 2.83283,2.82434 3.269,4.26902 4.5766,-1.88674 11.81084,-6.58439 13.15657,-8.57706 -5.45142,-4.19955 -10.79692,-6.33346 -16.51317,-8.30847 -1.59867,-0.71918 -2.87956,-1.22649 -0.71773,2.55635 0.98506,2.47275 0.85786,5.05143 0.57176,7.41825 0,0 -16.52749,0.40678 -28.23838,-2.1266 -2.92772,-0.63334 -5.46627,-0.95523 -7.21875,-1.89832 -0.87624,-0.47154 -1.48296,-0.8208 -1.91578,-1.3411 -0.43282,-0.5203 -0.2196,-1.29055 -0.20128,-1.85858 0.0366,-1.13607 0.25336,-1.67063 2.86177,-3.52492 2.60841,-1.85429 5.65407,-3.36195 11.65936,-5.81211 -0.0877,-1.29125 -0.29025,-2.5059 -1.29702,-2.99294 z" id="path2414" sodipodi:nodetypes="csssssccccccssssscc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2618);fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 269.62539,220.7482 c -1.43576,-0.13963 -2.58044,0.30288 -2.56084,1.50218 0.94391,0.85652 1.34942,2.43518 1.48562,3.14008 0.1362,0.7049 0.0359,1.21914 -0.48562,1.89004 -1.043,1.3418 -3.12498,1.56875 -6.5006,2.72063 -6.75124,2.30377 -16.89306,2.52561 -27.90689,3.84639 -22.02767,2.64157 -39.03164,3.76107 -39.03164,3.76107 1.98346,-4.64758 6.32828,-4.41197 6.34903,-8.20969 0.27376,-0.89755 -3.14597,-1.31638 -5.09943,-0.10731 -4.26694,3.70137 -7.59152,6.75353 -10.69418,10.51311 l 1.88795,3.08438 c 0,0 26.13006,-2.88973 48.19776,-5.5361 11.03385,-1.32318 20.95601,-1.99856 27.80968,-4.33728 3.42683,-1.16936 5.95975,-1.49022 7.6409,-3.51958 0.63172,-0.76256 1.35238,-3.04699 1.06804,-4.73369 -0.21951,-1.30213 -1.14979,-3.09774 -2.15978,-4.01423 z" id="path2608" sodipodi:nodetypes="ccsssscccccssssc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2630);fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 254.36185,220.33948 c -6.84997,3.24198 -7.15311,8.60912 -5.95953,12.79884 1.19358,4.18972 5.26293,8.75677 9.32121,12.40608 8.11656,7.29861 12.06046,9.33163 12.06046,9.33163 -3.71515,-0.10342 -7.89887,-1.41174 -8.13315,0.49304 -0.9483,2.97582 11.49137,3.47486 17.43787,2.70205 -1.39456,-7.57836 -3.79323,-13.21546 -7.73151,-14.90312 -1.68464,-0.14804 0.31242,4.72441 0.76985,9.39604 0,0 -3.62454,-1.73122 -11.60519,-8.90762 -3.99032,-3.5882 -7.37386,-7.3421 -8.47319,-11.20099 -1.09933,-3.85889 0.0776,-6.1205 4.95082,-9.53176 0.92816,-0.99528 -1.28985,-2.45913 -2.63764,-2.58419 z" id="path2620" sodipodi:nodetypes="csscccccsscc" inkscape:connector-curvature="0"/> + </g> + <path sodipodi:nodetypes="cccccc" id="rect2386" d="m 213.96569,234.57806 2.18756,-14.42897 15.21982,6.08793 21.49387,29.94828 -20.40591,9.21832 -18.49534,-30.82556 z" style="fill:url(#linearGradient2395);fill-opacity:1;stroke:none;display:inline" inkscape:connector-curvature="0"/> + <g id="g2649" style="display:inline"> + <path style="fill:url(#radialGradient2647);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" d="m 232.55816,219.5295 -15.92827,0.32199 3.08809,-15.15716 12.84018,14.83517 z" id="path1443" sodipodi:nodetypes="cccc" inkscape:connector-curvature="0"/> + <path style="fill:#812310;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 221.60041,219.29315 -4.41205,0.0782 0.85429,-3.98263 3.55776,3.90445 z" id="path1452" sodipodi:nodetypes="cccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2643);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" d="m 269.44172,159.27421 0.098,8.91471 8.0581,8.72344 7.75906,0.7992 -52.80669,41.84092 -6.66532,-3.30696 -5.08243,-5.618 -1.08987,-5.91194 49.72911,-45.44137 z" id="rect1437" sodipodi:nodetypes="ccccccccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2640);fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 268.94766,168.32844 8.3426,8.82719 -51.1007,38.68262 -4.9197,-5.4436 47.6778,-42.06621 z" id="rect1446" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0"/> + <path style="fill:#ffe965;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;display:inline" d="m 285.33776,177.73216 -8.16219,-0.86619 -7.7518,-8.67862 0.0132,-9.14293 8.36213,0.75209 7.18862,9.57682 0.35007,8.35883 z" id="path1440" sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0"/> + <path style="fill:#cb391c;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 280.72049,168.46367 0.1644,4.05654 -3.81335,-0.71676 -2.87504,-3.18901 -0.28089,-3.53393 3.85447,-0.16637 2.95041,3.54953 z" id="path1449" sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0"/> + </g> + <g id="g2657" style="display:inline"> + <path style="fill:url(#linearGradient2406);fill-opacity:1;stroke:none" d="m 183.88617,256.82796 0.99991,-16.30721 17.2878,8.44012 26.05488,38.00946 -29.28095,-1.13363 -15.06164,-29.00874 z" id="rect2397" sodipodi:nodetypes="cccccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2325);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline" d="m 200.90647,238.44836 -8.04601,15.77386 -7.05577,-13.57337 15.10178,-2.20049 z" id="rect2207" sodipodi:nodetypes="cccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2227);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" d="m 201.05389,238.55401 62.11704,24.91912 -7.88689,3.21429 -4.35152,9.30976 1.1716,9.96396 -59.31453,-31.72759 -0.49402,-7.36382 3.09592,-5.82826 5.6624,-2.48746 z" id="rect1328" sodipodi:nodetypes="ccccccccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#radialGradient2317);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline" d="m 255.27801,266.53504 7.9241,-3.04772 0.85337,10.24037 -3.9011,8.28983 -8.04601,3.77919 -1.341,-9.63083 4.51064,-9.63084 z" id="rect2204" sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0"/> + <path style="fill:url(#linearGradient2247);fill-opacity:1;stroke:none;display:inline" d="m 195.7549,241.421 59.13059,24.7962 -4.5917,9.76614 -57.48995,-29.00967 2.95106,-5.55267 z" id="rect2210" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0"/> + <path style="fill:#00b527;fill-opacity:1;stroke:none" d="m 255.02263,275.21029 2.08411,-4.1069 2.96459,-1.06995 0.69433,3.37197 -1.76759,3.85723 -3.15516,1.38315 -0.82028,-3.4355 z" id="rect2308" sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0"/> + <path style="fill:#258209;fill-opacity:1;stroke:none;display:inline" d="m 186.56849,241.00362 3.54963,-0.47312 -2.02297,3.53926 -1.52666,-3.06614 z" id="rect2327" sodipodi:nodetypes="cccc" inkscape:connector-curvature="0"/> + </g> + </g> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/domain-cart.png b/static/pix/domain-cart.png Binary files differnew file mode 100644 index 0000000..7f55880 --- /dev/null +++ b/static/pix/domain-cart.png diff --git a/static/pix/domain-search.png b/static/pix/domain-search.png Binary files differnew file mode 100644 index 0000000..e99ca2a --- /dev/null +++ b/static/pix/domain-search.png diff --git a/static/pix/ejabberd-admin.webp b/static/pix/ejabberd-admin.webp Binary files differnew file mode 100644 index 0000000..c84131f --- /dev/null +++ b/static/pix/ejabberd-admin.webp diff --git a/static/pix/ejabberd-login.webp b/static/pix/ejabberd-login.webp Binary files differnew file mode 100644 index 0000000..8ede74b --- /dev/null +++ b/static/pix/ejabberd-login.webp diff --git a/static/pix/ejabberd.png b/static/pix/ejabberd.png Binary files differnew file mode 100644 index 0000000..694e435 --- /dev/null +++ b/static/pix/ejabberd.png diff --git a/static/pix/element.svg b/static/pix/element.svg new file mode 100644 index 0000000..d29423e --- /dev/null +++ b/static/pix/element.svg @@ -0,0 +1,6 @@ +<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M19.4414 3.24C19.4414 1.4506 20.892 0 22.6814 0C34.6108 0 44.2814 9.67065 44.2814 21.6C44.2814 23.3894 42.8308 24.84 41.0414 24.84C39.252 24.84 37.8014 23.3894 37.8014 21.6C37.8014 13.2494 31.032 6.48 22.6814 6.48C20.892 6.48 19.4414 5.0294 19.4414 3.24Z" fill="#0DBD8B"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M34.5586 50.76C34.5586 52.5494 33.108 54 31.3186 54C19.3893 54 9.71861 44.3294 9.71861 32.4C9.71861 30.6106 11.1692 29.16 12.9586 29.16C14.748 29.16 16.1986 30.6106 16.1986 32.4C16.1986 40.7505 22.9681 47.52 31.3186 47.52C33.108 47.52 34.5586 48.9706 34.5586 50.76Z" fill="#0DBD8B"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M3.24 34.5601C1.4506 34.5601 -6.34076e-08 33.1095 -1.41625e-07 31.3201C-6.63074e-07 19.3907 9.67065 9.72007 21.6 9.72007C23.3894 9.72007 24.84 11.1707 24.84 12.9601C24.84 14.7495 23.3894 16.2001 21.6 16.2001C13.2495 16.2001 6.48 22.9695 6.48 31.3201C6.48 33.1095 5.0294 34.5601 3.24 34.5601Z" fill="#0DBD8B"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M50.76 19.4399C52.5494 19.4399 54 20.8905 54 22.6799C54 34.6093 44.3294 44.2799 32.4 44.2799C30.6106 44.2799 29.16 42.8293 29.16 41.0399C29.16 39.2505 30.6106 37.7999 32.4 37.7999C40.7505 37.7999 47.52 31.0305 47.52 22.6799C47.52 20.8905 48.9706 19.4399 50.76 19.4399Z" fill="#0DBD8B"/> +</svg>
\ No newline at end of file diff --git a/static/pix/fren_apu_tongue.png b/static/pix/fren_apu_tongue.png Binary files differnew file mode 100644 index 0000000..eb525be --- /dev/null +++ b/static/pix/fren_apu_tongue.png diff --git a/static/pix/git.svg b/static/pix/git.svg new file mode 100644 index 0000000..2e42bc7 --- /dev/null +++ b/static/pix/git.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="97px" height="97px" viewBox="0 0 97 97" enable-background="new 0 0 97 97" xml:space="preserve">
+<g>
+ <path fill="#F05133" d="M92.71,44.408L52.591,4.291c-2.31-2.311-6.057-2.311-8.369,0l-8.33,8.332L46.459,23.19
+ c2.456-0.83,5.272-0.273,7.229,1.685c1.969,1.97,2.521,4.81,1.67,7.275l10.186,10.185c2.465-0.85,5.307-0.3,7.275,1.671
+ c2.75,2.75,2.75,7.206,0,9.958c-2.752,2.751-7.208,2.751-9.961,0c-2.068-2.07-2.58-5.11-1.531-7.658l-9.5-9.499v24.997
+ c0.67,0.332,1.303,0.774,1.861,1.332c2.75,2.75,2.75,7.206,0,9.959c-2.75,2.749-7.209,2.749-9.957,0c-2.75-2.754-2.75-7.21,0-9.959
+ c0.68-0.679,1.467-1.193,2.307-1.537V36.369c-0.84-0.344-1.625-0.853-2.307-1.537c-2.083-2.082-2.584-5.14-1.516-7.698
+ L31.798,16.715L4.288,44.222c-2.311,2.313-2.311,6.06,0,8.371l40.121,40.118c2.31,2.311,6.056,2.311,8.369,0L92.71,52.779
+ C95.021,50.468,95.021,46.719,92.71,44.408z"/>
+</g>
+</svg>
diff --git a/static/pix/gitea.svg b/static/pix/gitea.svg new file mode 100644 index 0000000..9df6b83 --- /dev/null +++ b/static/pix/gitea.svg @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg version="1.1" id="main_outline" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" + y="0px" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640;" xml:space="preserve"> +<g> + <path id="teabag" style="fill:#FFFFFF" d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8 + c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4 + c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"/> + <g> + <g> + <path style="fill:#609926" d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2 + c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5 + c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5 + c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3 + c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1 + C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4 + c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7 + S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55 + c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8 + l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"/> + <path style="fill:#609926" d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4 + c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1 + c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9 + c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3 + c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3 + c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29 + c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8 + C343.2,346.5,335,363.3,326.8,380.1z"/> + </g> + </g> +</g> +</svg> diff --git a/static/pix/github.svg b/static/pix/github.svg new file mode 100644 index 0000000..93af7db --- /dev/null +++ b/static/pix/github.svg @@ -0,0 +1,3 @@ +<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#1B1F23"/> +</svg>
\ No newline at end of file diff --git a/static/pix/html-01.png b/static/pix/html-01.png Binary files differnew file mode 100644 index 0000000..c984971 --- /dev/null +++ b/static/pix/html-01.png diff --git a/static/pix/html-02.png b/static/pix/html-02.png Binary files differnew file mode 100644 index 0000000..d2f70d0 --- /dev/null +++ b/static/pix/html-02.png diff --git a/static/pix/html2-01.png b/static/pix/html2-01.png Binary files differnew file mode 100644 index 0000000..b808c0e --- /dev/null +++ b/static/pix/html2-01.png diff --git a/static/pix/i2p.svg b/static/pix/i2p.svg new file mode 100644 index 0000000..5dc629b --- /dev/null +++ b/static/pix/i2p.svg @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="302.66425" height="63.49197" id="svg5700"> + <defs id="defs5702"> + <pattern xlink:href="#pattern5595" id="pattern6495" patternTransform="matrix(1.2534787,-1.2534787,1.2534787,1.2534787,39.404452,317.94405)"/> + <pattern xlink:href="#Strips1_1" id="pattern5595" patternTransform="matrix(1.2534787,-1.2534787,1.2534787,1.2534787,39.404452,317.94405)"/> + <pattern id="Strips1_1" patternTransform="translate(0,0) scale(10,10)" height="1" width="2" patternUnits="userSpaceOnUse"> + <rect id="rect4774" height="2" width="1" y="-0.5" x="0" style="fill:black;stroke:none"/> + </pattern> + </defs> + <metadata id="metadata5705"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title/> + </cc:Work> + </rdf:RDF> + </metadata> + <g transform="translate(-221.9327,-428.83688)" id="layer1"> + <g transform="matrix(0.78302313,0,0,0.78302313,5.8401679,44.724391)" id="g5867"> + <g transform="matrix(1.7814702,0,0,1.6523316,-168.89205,-371.28852)" id="g4024" style="font-size:44.92046356px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:#edffd8;stroke-width:4.20006847;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS"> + <path d="m 300.61152,561.52647 0,-30.17163 9.8117,0 c 3.71812,3e-5 6.14177,0.15096 7.271,0.45279 1.7351,0.4528 3.18794,1.44068 4.35847,2.96365 1.17048,1.50929 1.75576,3.46447 1.75579,5.86555 -3e-5,1.85231 -0.33741,3.4096 -1.01217,4.67188 -0.67479,1.26231 -1.53547,2.25705 -2.58203,2.98423 -1.03283,0.71349 -2.0863,1.18685 -3.1604,1.42009 -1.45972,0.28814 -3.57355,0.4322 -6.34146,0.4322 l -2.46904,0 0,11.38124 -7.63186,0 m 7.63186,-25.61918 0,9.57218 1.8287,0 c 2.40987,0 4.02105,-0.15777 4.83355,-0.47337 0.81245,-0.31555 1.26535,-0.80949 1.71979,-1.48183 0.46819,-0.67228 0.70229,-1.91324 0.70231,-2.80511 -2e-5,-1.09762 -0.32362,-2.55481 -0.97084,-3.26831 -0.64724,-0.71344 -1.28604,-1.15935 -2.2775,-1.33775 -0.57409,-0.1079 -1.60396,-0.17337 -3.08959,-0.19642 -0.40317,-0.006 -0.8399,-0.009 -1.31019,-0.009 l -1.43623,0" id="path4030" style="font-weight:bold;stroke:#edffd8;stroke-width:4.20006847;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + <path d="m 258.19183,561.48828 0,-29.9626 7.92882,0 0,29.9626 -7.92882,0" id="path4026" style="font-weight:bold;stroke:#edffd8;stroke-width:4.20006847;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + <path d="m 294.21484,556.03391 0,5.45437 -21.60482,0 c 0.23396,-2.06192 0.93585,-4.01241 2.10565,-5.85143 1.1698,-1.85294 3.48016,-4.30496 6.93109,-7.35608 2.77827,-2.46595 4.48179,-4.13778 5.11058,-5.01552 0.84809,-1.21205 1.27214,-2.4102 1.27216,-3.59444 -2e-5,-1.30958 -0.37289,-2.31268 -1.11862,-3.00931 -0.73115,-0.7105 -1.74741,-1.06576 -3.04881,-1.06579 -1.28679,3e-5 -2.31037,0.36922 -3.07073,1.10759 -0.76038,0.73841 -1.19906,1.30905 -1.31603,3.02266 l -6.14147,-0.49155 c 0.36556,-3.23219 1.51343,-4.99012 3.44361,-6.39728 1.93017,-1.40709 4.34289,-2.11066 7.23816,-2.11069 3.17308,3e-5 5.66622,0.81506 7.47943,2.44507 1.81318,1.63006 2.71977,3.65716 2.7198,6.0813 -3e-5,1.37928 -0.26323,2.69585 -0.78962,3.94971 -0.51181,1.23997 -1.33067,2.5426 -2.45659,3.90792 -0.74577,0.90559 -2.09104,2.20824 -4.03582,3.90792 -1.94481,1.69972 -3.18042,2.8282 -3.70682,3.38548 -0.5118,0.55727 -0.92854,1.10062 -1.25022,1.63003 l 12.23484,0" id="path4028" style="font-weight:bold;stroke:#edffd8;stroke-width:4.20006847;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + </g> + <g transform="matrix(1.7814702,0,0,1.6523316,-168.89205,-371.28852)" id="g4032" style="font-size:44.92046356px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS"> + <path d="m 300.61152,561.52647 0,-30.17163 9.8117,0 c 3.71812,3e-5 6.14177,0.15096 7.271,0.45279 1.7351,0.4528 3.18794,1.44068 4.35847,2.96365 1.17048,1.50929 1.75576,3.46447 1.75579,5.86555 -3e-5,1.85231 -0.33741,3.4096 -1.01217,4.67188 -0.67479,1.26231 -1.53547,2.25705 -2.58203,2.98423 -1.03283,0.71349 -2.0863,1.18685 -3.1604,1.42009 -1.45972,0.28814 -3.57355,0.4322 -6.34146,0.4322 l -2.46904,0 0,11.38124 -7.63186,0 m 7.63186,-25.45694 0,9.36405 1.8287,0 c 2.40987,0 4.02105,-0.15777 4.83355,-0.47337 0.81245,-0.31555 1.20516,-0.80949 1.6596,-1.48183 0.46819,-0.67228 0.70229,-1.86735 0.70231,-2.75922 -2e-5,-1.09762 -0.32362,-2.39257 -0.97084,-3.10607 -0.64724,-0.71344 -1.22585,-1.15935 -2.21731,-1.33775 -0.72989,-0.13718 -2.19648,-0.20578 -4.39978,-0.20581 l -1.43623,0" id="path4034" style="font-weight:bold;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + <path d="m 258.19183,561.48828 0,-29.9626 7.92882,0 0,29.9626 -7.92882,0" id="path4036" style="font-weight:bold;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + <path d="m 294.21484,556.03391 0,5.45437 -21.60482,0 c 0.23396,-2.06192 0.93585,-4.01241 2.10565,-5.85143 1.1698,-1.85294 3.48016,-4.30496 6.93109,-7.35608 2.77827,-2.46595 4.48179,-4.13778 5.11058,-5.01552 0.84809,-1.21205 1.27214,-2.4102 1.27216,-3.59444 -2e-5,-1.30958 -0.37289,-2.31268 -1.11862,-3.00931 -0.73115,-0.7105 -1.74741,-1.06576 -3.04881,-1.06579 -1.28679,3e-5 -2.31037,0.36922 -3.07073,1.10759 -0.76038,0.73841 -1.19906,1.30905 -1.31603,3.02266 l -6.14147,-0.49155 c 0.36556,-3.23219 1.51343,-4.99012 3.44361,-6.39728 1.93017,-1.40709 4.34289,-2.11066 7.23816,-2.11069 3.17308,3e-5 5.66622,0.81506 7.47943,2.44507 1.81318,1.63006 2.71977,3.65716 2.7198,6.0813 -3e-5,1.37928 -0.26323,2.69585 -0.78962,3.94971 -0.51181,1.23997 -1.33067,2.5426 -2.45659,3.90792 -0.74577,0.90559 -2.09104,2.20824 -4.03582,3.90792 -1.94481,1.69972 -3.18042,2.8282 -3.70682,3.38548 -0.5118,0.55727 -0.92854,1.10062 -1.25022,1.63003 l 13.20114,0" id="path4038" style="font-weight:bold;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:Arial;-inkscape-font-specification:Arial Bold"/> + </g> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-220.60107,-448.68738)" id="path3798" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-220.60107,-433.72342)" id="path3800" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-220.60107,-418.75953)" id="path3802" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-220.60107,-403.79556)" id="path3804" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-205.89916,-448.68738)" id="path3806" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-205.89916,-433.72342)" id="path3808" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-205.89916,-418.75953)" id="path3810" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-205.89916,-403.79556)" id="path3812" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-191.19728,-448.68738)" id="path3814" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-191.19728,-433.72342)" id="path3816" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-191.19728,-418.75953)" id="path3818" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-191.19728,-403.79556)" id="path3820" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-176.49538,-448.68738)" id="path3822" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-176.49538,-433.72342)" id="path3824" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-176.49538,-418.75953)" id="path3826" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-176.49538,-403.79556)" id="path3828" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-161.79346,-448.68738)" id="path3865" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-161.79346,-433.72342)" id="path3867" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-161.79346,-418.75953)" id="path3869" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-161.79346,-403.79556)" id="path3871" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-147.09155,-448.68738)" id="path3873" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-147.09155,-433.72342)" id="path3875" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-147.09155,-418.75953)" id="path3877" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-147.09155,-403.79556)" id="path3879" style="fill:#ff0000;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-132.38967,-448.68738)" id="path3881" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-132.38967,-433.72342)" id="path3883" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-132.38967,-418.75953)" id="path3885" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-132.38967,-403.79556)" id="path3887" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-117.68777,-448.68738)" id="path3889" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-117.68777,-433.72342)" id="path3891" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-117.68777,-418.75953)" id="path3893" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-117.68777,-403.79556)" id="path3895" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-102.98586,-448.68738)" id="path3897" style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-102.98586,-433.72342)" id="path3899" style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-102.98586,-418.75953)" id="path3901" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-102.98586,-403.79556)" id="path3903" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-88.283964,-448.68738)" id="path3905" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-88.283964,-433.72342)" id="path3907" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-88.283964,-418.75953)" id="path3909" style="fill:#16ff0e;fill-opacity:0.85500536;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-88.283964,-403.79556)" id="path3911" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-73.582074,-448.68738)" id="path3913" style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-73.582074,-433.72342)" id="path3915" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-73.582074,-418.75953)" id="path3917" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-73.582074,-403.79556)" id="path3919" style="fill:#16ff0e;fill-opacity:0.85882562;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-58.880174,-448.68738)" id="path3921" style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-58.880174,-433.72342)" id="path3923" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-58.880174,-418.75953)" id="path3925" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-58.880174,-403.79556)" id="path3927" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-44.178254,-448.68738)" id="path3929" style="fill:#16ff0e;fill-opacity:0.85882562;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-44.178254,-433.72342)" id="path3931" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-44.178254,-418.75953)" id="path3933" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-44.178254,-403.79556)" id="path3935" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-29.476354,-448.68738)" id="path3937" style="fill:#ebed02;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-29.476354,-433.72342)" id="path3939" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-29.476354,-418.75953)" id="path3941" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-29.476354,-403.79556)" id="path3943" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-14.774464,-448.68738)" id="path3945" style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-14.774464,-433.72342)" id="path3947" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-14.774464,-418.75953)" id="path3949" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-14.774464,-403.79556)" id="path3951" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-0.07256439,-448.68738)" id="path3953" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-0.07256439,-433.72342)" id="path3955" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-0.07256439,-418.75953)" id="path3957" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + <path d="m 348.88224,513.22687 a 2.422795,2.422795 0 1 1 -4.84559,0 2.422795,2.422795 0 1 1 4.84559,0 z" transform="matrix(1.866199,0,0,1.866199,-0.07256439,-403.79556)" id="path3959" style="fill:#16ff0e;fill-opacity:1;stroke:none"/> + </g> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/imgcompress-cat.png b/static/pix/imgcompress-cat.png Binary files differnew file mode 100644 index 0000000..7243ae8 --- /dev/null +++ b/static/pix/imgcompress-cat.png diff --git a/static/pix/imgcompress-network.png b/static/pix/imgcompress-network.png Binary files differnew file mode 100644 index 0000000..09bc401 --- /dev/null +++ b/static/pix/imgcompress-network.png diff --git a/static/pix/inok.jpg b/static/pix/inok.jpg Binary files differnew file mode 100644 index 0000000..5bf7fdb --- /dev/null +++ b/static/pix/inok.jpg diff --git a/static/pix/irc.svg b/static/pix/irc.svg new file mode 100644 index 0000000..0f48379 --- /dev/null +++ b/static/pix/irc.svg @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" +"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<!-- Created with Inkscape (http://www.inkscape.org/) --><svg height="60.0000000" id="svg1" inkscape:version="0.38.1" sodipodi:docbase="/home/danny/flat/scalable/apps" sodipodi:docname="irc_protocol.svg" sodipodi:version="0.32" version="1.0" width="60.0000000" x="0" xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" y="0"> + <metadata> + <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <cc:Work rdf:about=""> + <dc:title>Part of the Flat Icon Collection (Wed Aug 25 23:23:49 2004)</dc:title> + <dc:description></dc:description> + <dc:subject> + <rdf:Bag> + <rdf:li>hash</rdf:li> + <rdf:li></rdf:li> + <rdf:li>application</rdf:li> + <rdf:li>computer</rdf:li> + <rdf:li>icons</rdf:li> + <rdf:li>theme</rdf:li> + </rdf:Bag> + </dc:subject> + <dc:publisher> + <cc:Agent rdf:about="http://www.openclipart.org"> + <dc:title>Danny Allen</dc:title> + </cc:Agent> + </dc:publisher> + <dc:creator> + <cc:Agent> + <dc:title>Danny Allen</dc:title> + </cc:Agent> + </dc:creator> + <dc:rights> + <cc:Agent> + <dc:title>Danny Allen</dc:title> + </cc:Agent> + </dc:rights> + <dc:date></dc:date> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/> + <dc:language>en</dc:language> + </cc:Work> + <cc:License rdf:about="http://web.resource.org/cc/PublicDomain"> + <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/> + <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/> + <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/> + </cc:License> + </rdf:RDF> + </metadata> + <sodipodi:namedview bordercolor="#ffffff" borderopacity="1.0" id="base" inkscape:cx="37.697545" inkscape:cy="22.126475" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="685" inkscape:window-width="1016" inkscape:window-x="0" inkscape:window-y="0" inkscape:zoom="6.9465337" pagecolor="#ffffff" showguides="true" snaptoguides="true"/> + <defs id="defs3"> + <linearGradient id="linearGradient772"> + <stop id="stop773" offset="0" style="stop-color:#fff;stop-opacity:1;"/> + <stop id="stop774" offset="1" style="stop-color:#fff;stop-opacity:1;"/> + </linearGradient> + <linearGradient id="linearGradient775" xlink:href="#linearGradient772"/> + </defs> + <path d="M 11.934141,39.676628 C 11.934141,39.055534 12.066954,38.483269 12.332579,37.959831 C 12.598204,37.432487 12.969298,37.018425 13.445860,36.717644 C 13.926329,36.416862 14.473204,36.266472 15.086485,36.266472 C 15.410704,36.266472 15.744688,36.305534 16.088438,36.383659 C 16.432188,36.457878 16.721251,36.586784 16.955626,36.770378 C 17.190001,36.953972 17.307188,37.202019 17.307188,37.514519 C 17.307188,37.764519 17.232970,37.973503 17.084532,38.141472 C 16.940001,38.309441 16.758360,38.393425 16.539610,38.393425 C 16.434141,38.393425 16.330626,38.375847 16.229063,38.340691 C 16.131407,38.305534 16.031798,38.268425 15.930235,38.229362 C 15.832579,38.186394 15.727110,38.151237 15.613829,38.123894 C 15.504454,38.096550 15.365782,38.082878 15.197813,38.082878 C 14.893126,38.082878 14.635313,38.155144 14.424376,38.299675 C 14.217345,38.440300 14.061095,38.631706 13.955626,38.873894 C 13.854063,39.112175 13.803282,39.379753 13.803282,39.676628 C 13.803282,39.965691 13.854063,40.235222 13.955626,40.485222 C 14.057188,40.731316 14.203673,40.926628 14.395079,41.071159 C 14.590391,41.215691 14.820860,41.287956 15.086485,41.287956 C 15.387266,41.287956 15.690001,41.231316 15.994688,41.118034 C 16.299376,41.004753 16.481016,40.948112 16.539610,40.948112 C 16.680235,40.948112 16.809141,40.989128 16.926329,41.071159 C 17.043516,41.153191 17.135313,41.260612 17.201720,41.393425 C 17.272032,41.522331 17.307188,41.655144 17.307188,41.791862 C 17.307188,42.080925 17.180235,42.325066 16.926329,42.524284 C 16.676329,42.723503 16.377501,42.868034 16.029845,42.957878 C 15.682188,43.051628 15.367735,43.098503 15.086485,43.098503 C 14.621641,43.098503 14.195860,43.012566 13.809141,42.840691 C 13.426329,42.668816 13.092345,42.424675 12.807188,42.108269 C 12.522032,41.787956 12.305235,41.420769 12.156798,41.006706 C 12.008360,40.588737 11.934141,40.145378 11.934141,39.676628 z M 7.9614851,41.991081 L 7.9614851,37.362175 C 7.9614851,37.084831 8.0474226,36.854362 8.2192976,36.670769 C 8.3950789,36.483269 8.6196883,36.389519 8.8931258,36.389519 C 9.1196883,36.389519 9.3150008,36.450066 9.4790633,36.571159 C 9.6470320,36.688347 9.7642195,36.827019 9.8306258,36.987175 C 10.232970,36.506706 10.664610,36.266472 11.125548,36.266472 C 11.379454,36.266472 11.602110,36.358269 11.793516,36.541862 C 11.988829,36.721550 12.086485,36.953972 12.086485,37.239128 C 12.086485,37.532097 11.994688,37.744987 11.811095,37.877800 C 11.631407,38.010612 11.332579,38.137566 10.914610,38.258659 C 10.488829,38.379753 10.201720,38.532097 10.053282,38.715691 C 9.9048445,38.895378 9.8306258,39.219597 9.8306258,39.688347 L 9.8306258,41.991081 C 9.8306258,42.268425 9.7427351,42.502800 9.5669539,42.694206 C 9.3950789,42.881706 9.1704695,42.975456 8.8931258,42.975456 C 8.6196883,42.975456 8.3950789,42.881706 8.2192976,42.694206 C 8.0474226,42.502800 7.9614851,42.268425 7.9614851,41.991081 z M 5.2603133,41.991081 L 5.2603133,37.362175 C 5.2603133,37.084831 5.3462508,36.854362 5.5181258,36.670769 C 5.6939070,36.483269 5.9185164,36.389519 6.1919539,36.389519 C 6.4692976,36.389519 6.6939070,36.483269 6.8657820,36.670769 C 7.0415633,36.854362 7.1294539,37.084831 7.1294539,37.362175 L 7.1294539,41.991081 C 7.1294539,42.268425 7.0415633,42.502800 6.8657820,42.694206 C 6.6939070,42.881706 6.4692976,42.975456 6.1919539,42.975456 C 5.9185164,42.975456 5.6939070,42.881706 5.5181258,42.694206 C 5.3462508,42.502800 5.2603133,42.268425 5.2603133,41.991081 z M 5.0786726,34.696159 C 5.0786726,34.391472 5.1880476,34.127800 5.4067976,33.905144 C 5.6255476,33.682487 5.8872664,33.571159 6.1919539,33.571159 C 6.5005476,33.571159 6.7642195,33.680534 6.9829695,33.899284 C 7.2017195,34.118034 7.3110945,34.383659 7.3110945,34.696159 C 7.3110945,35.020378 7.2017195,35.289909 6.9829695,35.504753 C 6.7642195,35.719597 6.5005476,35.827019 6.1919539,35.827019 C 5.8872664,35.827019 5.6255476,35.717644 5.4067976,35.498894 C 5.1880476,35.280144 5.0786726,35.012566 5.0786726,34.696159 z M -0.95648360,42.055534 L -0.74554610,40.479362 L -1.1967180,40.479362 C -1.3959367,40.479362 -1.5424211,40.422722 -1.6361711,40.309441 C -1.7299211,40.192253 -1.7767961,40.053581 -1.7767961,39.893425 C -1.7767961,39.733269 -1.7299211,39.598503 -1.6361711,39.489128 C -1.5424211,39.375847 -1.3959367,39.319206 -1.1967180,39.319206 L -0.58734298,39.319206 L -0.39398360,37.877800 L -0.85101485,37.877800 C -1.0463274,37.877800 -1.1908586,37.821159 -1.2846086,37.707878 C -1.3783586,37.590691 -1.4252336,37.452019 -1.4252336,37.291862 C -1.4252336,37.127800 -1.3783586,36.991081 -1.2846086,36.881706 C -1.1908586,36.768425 -1.0463274,36.711784 -0.85101485,36.711784 L -0.21820235,36.711784 L 0.039610147,34.830925 C 0.066953897,34.631706 0.12945390,34.477409 0.22711015,34.368034 C 0.32867265,34.258659 0.48882890,34.203972 0.70757890,34.203972 C 0.86382890,34.203972 0.99273515,34.248894 1.0942976,34.338737 C 1.1958601,34.424675 1.2466414,34.543816 1.2466414,34.696159 C 1.2466414,34.762566 1.2310164,34.907097 1.1997664,35.129753 L 0.98296952,36.711784 L 2.0669539,36.711784 L 2.3189070,34.830925 C 2.3462508,34.631706 2.4087508,34.477409 2.5064070,34.368034 C 2.6079695,34.258659 2.7681258,34.203972 2.9868758,34.203972 C 3.1431258,34.203972 3.2720320,34.248894 3.3735945,34.338737 C 3.4751570,34.428581 3.5259383,34.547722 3.5259383,34.696159 C 3.5259383,34.762566 3.5103133,34.907097 3.4790633,35.129753 L 3.2622664,36.711784 L 3.7192976,36.711784 C 3.9224226,36.711784 4.0689070,36.768425 4.1587508,36.881706 C 4.2525008,36.991081 4.2993758,37.127800 4.2993758,37.291862 C 4.2993758,37.452019 4.2525008,37.590691 4.1587508,37.707878 C 4.0650008,37.821159 3.9185164,37.877800 3.7192976,37.877800 L 3.1099226,37.877800 L 2.9165633,39.319206 L 3.3735945,39.319206 C 3.5767195,39.319206 3.7232039,39.373894 3.8130476,39.483269 C 3.9028914,39.592644 3.9478133,39.729362 3.9478133,39.893425 C 3.9478133,40.057487 3.9009383,40.196159 3.8071883,40.309441 C 3.7173445,40.422722 3.5728133,40.479362 3.3735945,40.479362 L 2.7349226,40.479362 L 2.4829695,42.354362 C 2.4556258,42.549675 2.3931258,42.702019 2.2954695,42.811394 C 2.1978133,42.920769 2.0376570,42.975456 1.8150008,42.975456 C 1.6587508,42.975456 1.5278914,42.932487 1.4224226,42.846550 C 1.3208601,42.756706 1.2700789,42.635612 1.2700789,42.483269 C 1.2700789,42.405144 1.2876570,42.262566 1.3228133,42.055534 L 1.5396101,40.479362 L 0.45562577,40.479362 L 0.20367265,42.354362 C 0.17632890,42.553581 0.11187577,42.707878 0.010313272,42.817253 C -0.087342978,42.922722 -0.24749923,42.975456 -0.47015548,42.975456 C -0.62249923,42.975456 -0.75140548,42.932487 -0.85687423,42.846550 C -0.95843673,42.756706 -1.0092180,42.635612 -1.0092180,42.483269 C -1.0092180,42.405144 -0.99163985,42.262566 -0.95648360,42.055534 z M 1.7153914,39.319206 L 1.9087508,37.877800 L 0.81890702,37.877800 L 0.62554765,39.319206 L 1.7153914,39.319206 z " id="path832" style="font-size:12.000000;font-weight:900;fill:#ffffff;stroke-width:1.0000000pt;font-family:VAG Rounded Black SSi;" transform="matrix(2.687231,-1.389012e-16,1.389012e-16,2.687231,8.790176,-72.34898)"/> +</svg> diff --git a/static/pix/irc/hexchat-connection-complete.png b/static/pix/irc/hexchat-connection-complete.png Binary files differnew file mode 100644 index 0000000..096ae01 --- /dev/null +++ b/static/pix/irc/hexchat-connection-complete.png diff --git a/static/pix/irc/hexchat-network-edit.png b/static/pix/irc/hexchat-network-edit.png Binary files differnew file mode 100644 index 0000000..4a0fb6f --- /dev/null +++ b/static/pix/irc/hexchat-network-edit.png diff --git a/static/pix/irc/hexchat-network-select.png b/static/pix/irc/hexchat-network-select.png Binary files differnew file mode 100644 index 0000000..9f4ffe3 --- /dev/null +++ b/static/pix/irc/hexchat-network-select.png diff --git a/static/pix/irc/hexchat-sasl.png b/static/pix/irc/hexchat-sasl.png Binary files differnew file mode 100644 index 0000000..ce77149 --- /dev/null +++ b/static/pix/irc/hexchat-sasl.png diff --git a/static/pix/irc/textual-identity.png b/static/pix/irc/textual-identity.png Binary files differnew file mode 100644 index 0000000..a2fce22 --- /dev/null +++ b/static/pix/irc/textual-identity.png diff --git a/static/pix/irc/textual-network-edit.png b/static/pix/irc/textual-network-edit.png Binary files differnew file mode 100644 index 0000000..1eb4dc7 --- /dev/null +++ b/static/pix/irc/textual-network-edit.png diff --git a/static/pix/itoopie.svg b/static/pix/itoopie.svg new file mode 100644 index 0000000..39e430d --- /dev/null +++ b/static/pix/itoopie.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512"><path fill="#010101" d="M153 239c-19.3 10-36 24.8-54.3 36.5-9.8 8.3-25.3 12.6-28.7 26 10.3 23 37.5 34 53.6 53 23.2 14.8 12.4 37.4 10.8 58.5-.6 19.8 8 38.2 19.5 53.8 0 14-32 35-4 41 32-.2 63 1.3 95 0 19-6.4 41 2.6 61-2.3 23-1.2 47-.3 70-2.6 23-16-28-31-1.6-47 14-18 10.7-42 5.5-62 18-15 18.3-37 20-58 5-20 14-39 19-59-4-24-39-42-46-57 18-29 27-64 20-98-6.6-55-51-101-105-113-60-15-128 17-155.5 72.5-16 31-18 68.4-9.4 102 5.6 20.4 17 38 29.6 54.4z"/><path fill="#576e57" d="M328 25l1 1z"/><path fill="#444b19" d="M267 26l1 1-1-1z"/><path fill="#ffff01" d="M180 329l18 8c9.2-17.5 14.8-38.4 21.6-57 2.3-6.3 3.5-17 9.5-21.2 5-3.3 15-.5 20 0 11 1 24 .7 34-1.7 53-11 90-57 92-111 3-73-69-132-141-117-44 10-76 44-88 86-10 38 2 79 28 107 7 8 15 14 24 20 3.8 3 10 5 11 10 1.4 6-4.3 14-6 19-6 20-16.4 39-21.2 59z"/><path fill="#444b19" d="M275 27l1 1-1-1m-39 1l1 1-1-1m-8 2l1 1-1-1z"/><path fill="#6c6c02" d="M291 31l1 1-1-1z"/><path fill="#989801" d="M207 38l1 1-1-1zm105 2l1 1-1-1z"/><path fill="#444b19" d="M313 40l1 1-1-1z"/><path fill="#6c6c02" d="M320 44l1 1-1-1z"/><path fill="#444b19" d="M321 45l1 1-1-1m-130 2l1 1-1-1z"/><path fill="#989801" d="M192 47l1 1-1-1zm-2 1l1 1-1-1z"/><path fill="#444b19" d="M326 48l1 1-1-1z"/><path fill="#989801" d="M327 49l1 1-1-1"/><path fill="#9fc79f" d="M359 50l1 1-1-1z"/><path fill="#989801" d="M186 51l1 1-1-1m-1 1l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#6c6c02" d="M182 54l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#9fc79f" d="M334 55l1 1-1-1z"/><path fill="#6c6c02" d="M180 56l1 1-1-1z"/><path fill="#989801" d="M179 57l1 1-1-1m-1 1l1 1-1-1m-1 1l1 1z"/><path fill="#6c6c02" d="M176 60l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#989801" d="M341 61l1 1-1-1z"/><path fill="#6c6c02" d="M174 62l1 1-1-1z"/><path fill="#989801" d="M342 62l1 1-1-1z"/><path fill="#6c6c02" d="M173 63l1 1-1-1z"/><path fill="#989801" d="M343 63l1 1-1-1m-171 1l1 1-1-1m172 0l1 1-1-1m-173 1l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#010101" d="M299 75.5c-52.4 11-36.2 92.8 16 81.7 52.7-11.2 36.3-92.8-16-81.7z"/><path fill="#444b19" d="M354 77l1 1-1-1z"/><path fill="#6c6c02" d="M161 78l1 1-1-1z"/><path fill="#010101" d="M203 78.4c-42 5.6-52.3 62.7-12 80 7.5 3 18 2.6 26 1.4 48.6-7.5 34.8-87.8-14-81.4z"/><path fill="#989801" d="M289 78l1 1-1-1m35 0l1 1-1-1z"/><path fill="#444b19" d="M355 78l1 1-1-1z"/><path fill="#989801" d="M221 80l1 1-1-1z"/><path fill="#9fc79f" d="M328 80l1 1-1-1z"/><path fill="#6c6c02" d="M356 80l1 1-1-1zm-74 2l1 1-1-1z"/><path fill="#444b19" d="M185 83l1 1-1-1z"/><path fill="#989801" d="M281 83l1 1-1-1z"/><path fill="#6c6c02" d="M358 83l1 1-1-1m-174 1l1 1-1-1z"/><path fill="#444b19" d="M228 84l1 1-1-1z"/><path fill="#989801" d="M280 84l1 1-1-1z"/><path fill="#444b19" d="M359 84l1 1-1-1z"/><path fill="#6c6c02" d="M182 85l1 1-1-1m48 0l1 1-1-1z"/><path fill="#444b19" d="M334 85l1 1-1-1z"/><path fill="#6c6c02" d="M359 85l1 1-1-1m-203 1l1 1-1-1m25 0l1 1-1-1m50 0l1 1-1-1z"/><path fill="#989801" d="M277 86l1 1-1-1z"/><path fill="#444b19" d="M305 86l1 1-1-1zm30 0l1 1-1-1zm-103 1l1 1-1-1z"/><path fill="#989801" d="M276 87l1 1-1-1z"/><path fill="#fff" d="M283 134c3-6.3 4.8-9.4 10.2-11.7 15.7-7 24.5 8.4 22.8 21.7 38.8-11.2 14-72-22-54-4.3 2.3-8.2 6-11 10-3 4.5-5.2 9.5-5.7 15-.6 7 2.6 13 5.7 19z"/><path fill="#989801" d="M360 87l1 1-1-1m-205 1l1 1-1-1z"/><path fill="#6c6c02" d="M178 88l1 1-1-1z"/><path fill="#444b19" d="M276 88l1 1z"/><path fill="#576e57" d="M297 88l1 1-1-1z"/><path fill="#444b19" d="M235 89l1 1-1-1z"/><path fill="#6c6c02" d="M275 89l1 1-1-1z"/><path fill="#779375" d="M319 89l1 1-1-1z"/><path fill="#9fc79f" d="M201 90l1 1-1-1z"/><path fill="#FFF" d="M196 147c-2-8-3-15 3.4-21.8 10.5-11 28.7-3.6 30.6 10.8 9.5-9.4 6-29.2-3.2-37.7-12.5-11.8-32-10.4-43 2.7-3.6 4.5-5.2 9.2-6 15-.8 5.6.2 12 2.5 17 3.2 6.8 9 11.2 15.7 14z"/><path fill="#989801" d="M274 90l1 1-1-1z"/><path fill="#576e57" d="M320 90l1 1-1-1z"/><path fill="#989801" d="M175 91l1 1z"/><path fill="#444b19" d="M197 91l1 1-1-1z"/><path fill="#576e57" d="M215 91l1 1-1-1z"/><path fill="#989801" d="M273 91l1 1-1-1z"/><path fill="#9fc79f" d="M291 91l1 1-1-1zm-1 1l1 1-1-1z"/><path fill="#444b19" d="M324 92l1 1-1-1z"/><path fill="#6c6c02" d="M238 93l1 1-1-1m34 0l1 1-1-1z"/><path fill="#576e57" d="M288 93l1 1-1-1z"/><path fill="#95bb95" d="M289 93l1 1-1-1z"/><path fill="#444b19" d="M325 93l1 1-1-1z"/><path fill="#6c6c02" d="M173 94l1 1-1-1z"/><path fill="#9fc79f" d="M191 94l1 1-1-1z"/><path fill="#779375" d="M221 94l1 1-1-1z"/><path fill="#444b19" d="M222 94l1 1-1-1"/><path fill="#6c6c02" d="M271 94l1 1-1-1z"/><path fill="#95bb95" d="M287 94l1 1-1-1z"/><path fill="#779375" d="M326 94l1 1-1-1z"/><path fill="#444b19" d="M240 95l1 1-1-1z"/><path fill="#9fc79f" d="M286 95l1 1-1-1z"/><path fill="#989801" d="M364 95l1 1z"/><path fill="#9fc79f" d="M285 96l1 1-1-1zm-1 1l1 1-1-1z"/><path fill="#576e57" d="M126 99l1 1-1-1z"/><path fill="#9fc79f" d="M185 99l1 1-1-1z"/><path fill="#444b19" d="M366 99l1 1-1-1z"/><path fill="#6c6c02" d="M169 100l1 1-1-1z"/><path fill="#9fc79f" d="M184 100l1 1-1-1z"/><path fill="#989801" d="M345 100l1 1-1-1m21 0l1 1-1-1z"/><path fill="#6c6c02" d="M149 101l1 1-1-1z"/><path fill="#9fc79f" d="M182 102l1 1-1-1z"/><path fill="#444b19" d="M230 102l1 1-1-1z"/><path fill="#6c6c02" d="M244 102l1 1-1-1z"/><path fill="#444b19" d="M346 103l1 1-1-1zm-113 4l1 1-1-1z"/><path fill="#989801" d="M166 108l1 1-1-1z"/><path fill="#6c6c02" d="M246 108l1 1-1-1z"/><path fill="#576e57" d="M278 108l1 1-1-1"/><path fill="#444b19" d="M369 108l1 1-1-1m-223 1l1 1-1-1z"/><path fill="#576e57" d="M178 109l1 1-1-1z"/><path fill="#95bb95" d="M234 110l1 1-1-1z"/><path fill="#444b19" d="M372 117l1 1-1-1z"/><path fill="#576e57" d="M213 119l1 1-1-1z"/><path fill="#779375" d="M206 120l1 1-1-1"/><path fill="#9fc79f" d="M295 121l1 1-1-1z"/><path fill="#576e57" d="M304 121l1 1-1-1z"/><path fill="#444b19" d="M221 122l1 1-1-1z"/><path fill="#6c6c02" d="M143 123l1 1-1-1z"/><path fill="#9fc79f" d="M200 123l1 1-1-1z"/><path fill="#576e57" d="M223 123l1 1-1-1z"/><path fill="#9fc79f" d="M199 124l1 1-1-1z"/><path fill="#576e57" d="M224 124l1 1-1-1m54 0l1 1-1-1z"/><path fill="#9fc79f" d="M289 124l1 1-1-1z"/><path fill="#926a61" d="M310 124l1 1-1-1z"/><path fill="#95bb95" d="M311 124l1 1-1-1z"/><path fill="#9fc79f" d="M198 125l1 1-1-1z"/><path fill="#444b19" d="M225 125l1 1-1-1z"/><path fill="#989801" d="M247 125l1 1-1-1z"/><path fill="#6c6c02" d="M266 125l1 1-1-1z"/><path fill="#9fc79f" d="M312 125l1 1-1-1z"/><path fill="#444b19" d="M166 130l1 1-1-1z"/><path fill="#9fc79f" d="M195 130l1 1-1-1z"/><path fill="#95bb95" d="M315 130l1 1-1-1z"/><path fill="#926a61" d="M179 131l1 1-1-1z"/><path fill="#9fc79f" d="M229 131l1 1-1-1z"/><path fill="#779375" d="M233 131l1 1-1-1z"/><path fill="#576e57" d="M281 131l1 1-1-1z"/><path fill="#95bb95" d="M284 131l1 1-1-1z"/><path fill="#9fc79f" d="M282 132l1 1-1-1z"/><path fill="#989801" d="M345 132l1 1-1-1m-178 1l1 1-1-1z"/><path fill="#444b19" d="M180 133l1 1-1-1z"/><path fill="#576e57" d="M194 133l1 1-1-1z"/><path fill="#444b19" d="M232 133l1 1-1-1zm-1 2l1 1-1-1"/><path fill="#6c6c02" d="M169 138l1 1-1-1z"/><path fill="#444b19" d="M243 138l1 1-1-1m28 0l1 1-1-1z"/><path fill="#6c6c02" d="M342 138l1 1-1-1z"/><path fill="#9fc79f" d="M169 139l1 1-1-1z"/><path fill="#989801" d="M243 139l1 1-1-1z"/><path fill="#6c6c02" d="M272 139l1 1-1-1z"/><path fill="#444b19" d="M325 139l1 1-1-1z"/><path fill="#9fc79f" d="M342 139l1 1-1-1m-100 1l1 1-1-1z"/><path fill="#989801" d="M273 141l1 1-1-1z"/><path fill="#6c6c02" d="M274 142l1 1-1-1zm1 1l1 1-1-1z"/><path fill="#444b19" d="M190 144l1 1-1-1z"/><path fill="#6c6c02" d="M276 144l1 1-1-1z"/><path fill="#576e57" d="M192 145l1 1-1-1z"/><path fill="#444b19" d="M237 146l1 1-1-1z"/><path fill="#6c6c02" d="M175 147l1 1z"/><path fill="#989801" d="M237 147l1 1-1-1m42 0l1 1-1-1z"/><path fill="#6c6c02" d="M176 148l1 1-1-1z"/><path fill="#444b19" d="M236 148l1 1-1-1z"/><path fill="#989801" d="M280 148l1 1-1-1z"/><path fill="#444b19" d="M177 149l1 1-1-1z"/><path fill="#989801" d="M281 149l1 1-1-1z"/><path fill="#444b19" d="M178 150l1 1-1-1z"/><path fill="#6c6c02" d="M282 150l1 1-1-1z"/><path fill="#989801" d="M328 152l1 1-1-1z"/><path fill="#444b19" d="M182 153l1 1-1-1z"/><path fill="#6c6c02" d="M325 153l1 1-1-1z"/><path fill="#989801" d="M326 153l1 1-1-1"/><path fill="#444b19" d="M184 154l1 1-1-1z"/><path fill="#989801" d="M229 154l1 1-1-1"/><path fill="#6c6c02" d="M320 155l1 1-1-1z"/><path fill="#989801" d="M223 157l1 1-1-1m-32 1l1 1z"/><path fill="#9fc79f" d="M215 160l1 1-1-1z"/><path fill="#6c6c02" d="M143 162l1 1zm226 15l1 1-1-1z"/><path fill="#989801" d="M367 183l1 1z"/><path fill="#6c6c02" d="M149 184l1 1-1-1z"/><path fill="#989801" d="M366 185l1 1-1-1z"/><path fill="#444b19" d="M366 186l1 1-1-1z"/><path fill="#576e57" d="M390 187l1 1-1-1z"/><path fill="#989801" d="M364 190l1 1-1-1m-212 1l1 1-1-1z"/><path fill="#444b19" d="M364 191l1 1-1-1z"/><path fill="#989801" d="M153 193l1 1-1-1m207 5l1 1z"/><path fill="#6c6c02" d="M156 199l1 1-1-1z"/><path fill="#444b19" d="M157 200l1 1-1-1z"/><path fill="#6c6c02" d="M359 200l1 1-1-1z"/><path fill="#444b19" d="M359 201l1 1-1-1z"/><path fill="#989801" d="M161 207l1 1-1-1z"/><path fill="#444b19" d="M355 207l1 1-1-1z"/><path fill="#989801" d="M162.3 208.7c-108.2 202.2-54 101 0 0z"/><path fill="#444b19" d="M354 208l1 1-1-1z"/><path fill="#989801" d="M163 210l1 1-1-1m3 4l1 1-1-1m1 1l1 1-1-1m182 0l1 1-1-1m-181 1l1 1-1-1zm2 3l1 1-1-1m1 1l1 1-1-1m1 1l1 1-1-1m172 0l1 1-1-1z"/><path fill="#6c6c02" d="M173 222l1 1-1-1z"/><path fill="#989801" d="M343 222l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#6c6c02" d="M175 224l1 1-1-1z"/><path fill="#989801" d="M341 224l1 1-1-1z"/><path fill="#6c6c02" d="M176 225l1 1-1-1z"/><path fill="#989801" d="M177 226l1 1-1-1m1 1l1 1-1-1m1 1l1 1-1-1m158 0l1 1-1-1z"/><path fill="#6c6c02" d="M180 229l1 1-1-1z"/><path fill="#989801" d="M336 229l1 1-1-1z"/><path fill="#6c6c02" d="M181 230l1 1-1-1z"/><path fill="#989801" d="M334 230l1 1-1-1z"/><path fill="#444b19" d="M335 230l1 1-1-1z"/><path fill="#6c6c02" d="M182 231l1 1-1-1z"/><path fill="#989801" d="M184 232l1 1-1-1m1 1l1 1-1-1m1 1l1 1-1-1m1 1l1 1-1-1m3 2l1 1z"/><path fill="#6c6c02" d="M326 237l1 1-1-1z"/><path fill="#444b19" d="M191 238l1 1-1-1z"/><path fill="#989801" d="M192 238l1 1-1-1z"/><path fill="#6c6c02" d="M320 241l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#5a081a" d="M334 248c-222.7 176-111.3 88 0 0z"/><path fill="#ff013d" d="M237 270c-8.5 16-15.4 36.6-20 54-1.4 5-6.3 11.7-5 17 3.2 12.8 17.2 22.5 29 25.6 22.3 5.8 48.2 7.5 70-1 4-1.6 9.7-3 12-6.8 2-3.6.8-9 1.2-12.8 1-10.2 6.5-18.5 16.8-21 0-9 1.7-18.7 8.5-25.5 4-4 10.2-6 14-1.2 9.8 12.3-3.6 27.7 12.5 36.7 13.8-29.4 26.3-75-15-88.7-5.2-1.8-11.4-4.7-17-4-10.3 1-22.7 14-32.4 18.6-22.3 10-50.6 14-74.6 9z"/><path fill="#444b19" d="M199 243l1 1-1-1z"/><path fill="#989801" d="M315 244l1 1z"/><path fill="#444b19" d="M202 245l1 1-1-1z"/><path fill="#989801" d="M313 245l1 1-1-1z"/><path fill="#6c6c02" d="M314 245l1 1-1-1z"/><path fill="#989801" d="M311 246l1 1-1-1z"/><path fill="#444b19" d="M205 247l1 1-1-1z"/><path fill="#5a081a" d="M365 247l1 1-1-1z"/><path fill="#6c6c02" d="M206.7 249.3c-137.8 175-69 87.6 0 0z"/><path fill="#576e57" d="M401 250l1 1-1-1z"/><path fill="#5a081a" d="M181 251c-120.7 174-60.3 87 0 0zm147 0l1 1-1-1z"/><path fill="#a30127" d="M181 253c-120.7 172.7-60.3 86.3 0 0z"/><path fill="#ff013d" d="M137 338c3.2-4.2 6.6-7.2 11-10-2-4-6.7-6.5-7.5-11-1.6-9.4 12.2-21 20.5-21.8 4.4-.5 12.3 5 15.5 3 2.5-1.7 3.4-6.6 4.5-9.2 3-7.5 13-26 8-33.7-2.5-4-7.7-3.8-13.4-2.2-7.6 3-16 8-19.6 10-13.6 8-26.5 17-39 27-4 3-12.3 8-13.5 13-1.2 6 3 11 6.2 14 7.7 9 17.2 17 27.3 22z"/><path fill="#a30127" d="M185.7 252.3c-123.8 173-62 86.6 0 0zM170 255l1 1-1-1z"/><path fill="#989801" d="M289 255l1 1-1-1z"/><path fill="#a30127" d="M320 256l1 1-1-1z"/><path fill="#444b19" d="M230 257l1 1-1-1z"/><path fill="#989801" d="M281 257l1 1-1-1z"/><path fill="#5a081a" d="M318 257l1 1-1-1zm-154.7 1.7c-109 169-54.4 84.4 0 0z"/><path fill="#6c6c02" d="M205 258l1 1-1-1m23 0l1 1-1-1z"/><path fill="#5a081a" d="M161 259l1 1z"/><path fill="#6c6c02" d="M227 259l1 1-1-1z"/><path fill="#a30127" d="M160.3 260.7c-107 167.5-53.4 83.7 0 0z"/><path fill="#444b19" d="M226 260l1 1-1-1z"/><path fill="#a30127" d="M154 263l1 1-1-1"/><path fill="#989801" d="M223 267l1 1-1-1z"/><path fill="#5a081a" d="M386 267l1 1-1-1m-198 1l1 1-1-1z"/><path fill="#989801" d="M201 268l1 1-1-1z"/><path fill="#444b19" d="M223.3 268.7c-149 162.2-74.4 81 0 0z"/><path fill="#6c6c02" d="M222 270c-148 161.3-74 80.7 0 0z"/><path fill="#5a081a" d="M236 270l1 1-1-1z"/><path fill="#989801" d="M200 271c-133.3 160.7-66.7 80.3 0 0z"/><path fill="#5a081a" d="M245 271l1 1-1-1"/><path fill="#a30127" d="M139 273l1 1-1-1z"/><path fill="#5a081a" d="M186.3 273.7c-124.2 159-62 79.4 0 0z"/><path fill="#a30127" d="M137 274l1 1-1-1z"/><path fill="#6c6c02" d="M199 274l1 1-1-1z"/><path fill="#a30127" d="M185 275l1 1z"/><path fill="#444b19" d="M198.5 276.6c-132.3 157-66.2 78.5 0 0z"/><path fill="#a30127" d="M234 275l1 1-1-1zm-100 1l1 1-1-1zm-1 1l1 1-1-1z"/><path fill="#5a081a" d="M131 278l1 1-1-1m53.3.7s0 1 .4.6c0 0 0-1-.4-.6zm-54.3.3l1 1-1-1z"/><path fill="#a30127" d="M183.3 280.7c-122.2 154.2-61 77 0 0z"/><path fill="#5a081a" d="M127 281l1 1-1-1z"/><path fill="#a30127" d="M125.7 282.3c-.5.5.6.4.6.4.5-.5-.6-.4-.6-.4z"/><path fill="#6c6c02" d="M218 282l1 1-1-1z"/><path fill="#5a081a" d="M231 282l1 1-1-1m-107 1l1 1-1-1z"/><path fill="#9fc79f" d="M83 286l1 1-1-1z"/><path fill="#444b19" d="M216.3 287.7c-144.2 149.5-72 74.7 0 0z"/><path fill="#a30127" d="M180 289l1 1-1-1z"/><path fill="#989801" d="M215 289c-143.3 148.7-71.7 74.3 0 0z"/><path fill="#6c6c02" d="M193 290l1 1-1-1m22.3.7s0 1 .4.6c0 0 0-1-.4-.6z"/><path fill="#989801" d="M192.3 293.7c-128.2 145.5-64 72.7 0 0z"/><path fill="#a30127" d="M109 295l1 1-1-1m57 0c-110.7 144.7-55.3 72.3 0 0z"/><path fill="#5a081a" d="M178.3 295.7c-119 144.2-59.4 72 0 0z"/><path fill="#6c6c02" d="M191.3 295.7c-127.5 144.2-63.7 72 0 0z"/><path fill="#989801" d="M213 295l1 1-1-1z"/><path fill="#a30127" d="M108 296l1 1-1-1m46.7.3c-103 143.8-51.6 72 0 0z"/><path fill="#6c6c02" d="M213 296l1 1-1-1z"/><path fill="#a30127" d="M107 297l1 1z"/><path fill="#5a081a" d="M171.3 297.7c-114.2 143-57 71.4 0 0z"/><path fill="#989801" d="M191 297l1 1-1-1z"/><path fill="#a30127" d="M226 297l1 1-1-1m-119.7 1.7c-71 142.2-35.4 71 0 0z"/><path fill="#5a081a" d="M177 298l1 1-1-1z"/><path fill="#444b19" d="M190.3 298.7c-127 142.2-63.4 71 0 0z"/><path fill="#5a081a" d="M173.7 299.3c-115.8 141.8-58 71 0 0z"/><path fill="#a30127" d="M176 299l1 1-1-1m-74 3c-68 140-34 70 0 0z"/><path fill="#5a081a" d="M147 302c1 1 1 1 0 0"/><path fill="#6c6c02" d="M188 304l1 1-1-1z"/><path fill="#989801" d="M210 304l1 1-1-1z"/><path fill="#6c6c02" d="M209 306l1 1-1-1z"/><path fill="#444b19" d="M208 312c-138.7 133.3-69.3 66.7 0 0z"/><path fill="#a30127" d="M106 312l1 1z"/><path fill="#444b19" d="M185 312l1 1-1-1z"/><path fill="#6c6c02" d="M207.3 312.7c-138.2 133-69 66.4 0 0z"/><path fill="#a30127" d="M107 313l1 1-1-1z"/><path fill="#5a081a" d="M140 313c-93.3 132.7-46.7 66.3 0 0z"/><path fill="#989801" d="M185 313l1 1-1-1z"/><path fill="#a30127" d="M108 314l1 1-1-1z"/><path fill="#989801" d="M206.3 314.7c-137.5 131.5-68.7 65.7 0 0z"/><path fill="#a30127" d="M109 315l1 1-1-1m1.3 1.7c-73.5 130.2-36.7 65 0 0z"/><path fill="#444b19" d="M183.3 317.7c-122.2 129.5-61 64.7 0 0z"/><path fill="#a30127" d="M111 318l1 1-1-1m1 1l1 1-1-1z"/><path fill="#989801" d="M183 319l1 1-1-1z"/><path fill="#5a081a" d="M218 319l1 1-1-1z"/><path fill="#a30127" d="M382 320l1 1-1-1m-267 1l1 1-1-1m1 1l1 1zm1 1l1 1-1-1m1 1l1 1-1-1m28 1l1 1-1-1m2.3 1.7c-99 123.5-49.4 61.7 0 0z"/><path fill="#444b19" d="M180 326l1 1-1-1z"/><path fill="#a30127" d="M335 326l1 1-1-1m-213 1l1 1-1-1m93.3.7c-143.5 123-71.7 61.4 0 0zm-92.3.3l1 1-1-1z"/><path fill="#5a081a" d="M147 328l1 1-1-1z"/><path fill="#6c6c02" d="M201 328l1 1-1-1z"/><path fill="#444b19" d="M201.3 329.7c-134.2 121.5-67 60.7 0 0z"/><path fill="#5a081a" d="M214.3 329.7c-143 121.5-71.4 60.7 0 0z"/><path fill="#989801" d="M184 330l1 1-1-1z"/><path fill="#5a081a" d="M373 333l1 1z"/><path fill="#444b19" d="M191 334l1 1-1-1z"/><path fill="#989801" d="M192 334l1 1-1-1z"/><path fill="#6c6c02" d="M199 334l1 1-1-1z"/><path fill="#a30127" d="M327 334l1 1-1-1z"/><path fill="#5a081a" d="M374 334l1 1-1-1z"/><path fill="#6c6c02" d="M194.3 335.7c-129.5 117.5-64.7 58.7 0 0z"/><path fill="#5a081a" d="M375 335l1 1-1-1m-241.3 1.3c-89 117-44.6 58.6 0 0z"/><path fill="#444b19" d="M195 336l1 1-1-1z"/><path fill="#989801" d="M198.3 336.7c-132.2 117-66 58.4 0 0z"/><path fill="#9fc79f" d="M104 337l1 1-1-1z"/><path fill="#444b19" d="M197 337l1 1-1-1z"/><path fill="#926a61" d="M343 338l1 1-1-1z"/><path fill="#fbb5a7" d="M344 338.7c-8.5 3.5-8.5 27.2-1.4 32.3 3.8 2.8 17.2-.7 21.4-2.3 23.5-9.5-4.6-36-20-30z"/><path fill="#444b19" d="M341 339l1 1-1-1m-1 1l1 1-1-1z"/><path fill="#926a61" d="M357 340l1 1-1-1z"/><path fill="#a30127" d="M211 341l1 1-1-1zm1 1l1 1-1-1z"/><path fill="#926a61" d="M339 342l1 1-1-1m22 0l1 1-1-1z"/><path fill="#5a081a" d="M324 343l1 1-1-1z"/><path fill="#b9867c" d="M159 344c-106 112-53 56 0 0z"/><path fill="#a30127" d="M213 344l1 1-1-1z"/><path fill="#444b19" d="M364 344l1 1-1-1z"/><path fill="#fbb5a7" d="M201 365c-6.8-9-22-17.4-33-19.5-4.5-1-12.2-1.7-14.2 3.6-2.6 7 4 13 9.2 16 11.8 6 26 4 38 1z"/><path fill="#926a61" d="M168 345l1 1-1-1z"/><path fill="#5a081a" d="M214.3 345.7c-143 111-71.4 55.4 0 0z"/><path fill="#444b19" d="M365 345l1 1-1-1z"/><path fill="#a30127" d="M215 347l1 1-1-1z"/><path fill="#b9867c" d="M176 348l1 1-1-1z"/><path fill="#444b19" d="M178.7 349.3c-119 108.5-59.6 54.3 0 0z"/><path fill="#5a081a" d="M216 349l1 1-1-1z"/><path fill="#926a61" d="M180.7 350.3c-120.5 107.8-60.3 54 0 0z"/><path fill="#5a081a" d="M217 350l1 1-1-1z"/><path fill="#444b19" d="M370 350l1 1-1-1z"/><path fill="#b9867c" d="M182 351l1 1-1-1z"/><path fill="#576e57" d="M183 351l1 1-1-1z"/><path fill="#5a081a" d="M218 351l1 1-1-1z"/><path fill="#576e57" d="M371 351l1 1-1-1z"/><path fill="#444b19" d="M185 352l1 1-1-1zm-32 2c-102 105.3-51 52.7 0 0z"/><path fill="#5a081a" d="M222 356l1 1-1-1"/><path fill="#926a61" d="M192 357l1 1-1-1z"/><path fill="#5a081a" d="M223 357l1 1-1-1z"/><path fill="#b9867c" d="M155 358l1 1-1-1z"/><path fill="#444b19" d="M338 358l1 1-1-1z"/><path fill="#b9867c" d="M194.7 359.3c-129.8 101.8-65 51 0 0z"/><path fill="#5a081a" d="M320 361l1 1-1-1z"/><path fill="#926a61" d="M199 362l1 1-1-1z"/><path fill="#a30127" d="M319 362l1 1-1-1z"/><path fill="#926a61" d="M200 363l1 1-1-1z"/><path fill="#5a081a" d="M229 363l1 1-1-1z"/><path fill="#444b19" d="M161 364l1 1-1-1z"/><path fill="#926a61" d="M162 364l1 1-1-1m39 0l-1 2h2c0-2 .3-1.4-1-2z"/><path fill="#444b19" d="M163.7 365.3c-109 97.8-54.6 49 0 0z"/><path fill="#b9867c" d="M199 365l1 1-1-1z"/><path fill="#5a081a" d="M311.7 365.3c-207.8 97.8-104 49 0 0z"/><path fill="#444b19" d="M196 366c-130.7 97.3-65.3 48.7 0 0z"/><path fill="#576e57" d="M134 367l1 1-1-1z"/><path fill="#b9867c" d="M191 367l1 1-1-1z"/><path fill="#a30127" d="M244 367l1 1-1-1m61 0l1 1-1-1z"/><path fill="#444b19" d="M366 367l1 1-1-1z"/><path fill="#926a61" d="M364 368l1 1-1-1z"/><path fill="#5a081a" d="M298 369l1 1-1-1z"/><path fill="#95bb95" d="M357 385c-17 3.2-27 3-31-16-12 1.6-23.6 7.8-36 9.6-4 .6-11-1-14.3 2-5 4.8-5.4 14-5.7 20.4-.3 4.7-2.4 9.3-1.6 14 1.7 10.3 13.3 21.2 19.7 29 5 5.7 11 14.3 18 16.5 9 2.4 17-4.7 23-8.8 10-6 20-13.5 25-23.7 3-4.8 1-11.8 1-17 1-8.7 2-17.3 2-26z"/><path fill="#444b19" d="M358 370l1 1-1-1z"/><path fill="#576e57" d="M305 375l1 1-1-1z"/><path fill="#9fc79f" d="M157 384c0 14-.5 26 5.2 39 4.8 11 11 21 19 30 7 7.7 14.8 9 24.8 9 17.2 0 33.7-6.2 42.5-22 11-20 3.6-55-21.5-61.3-8-2-23.7 6.3-32 8-13.7 3-24.8-.4-38-2.7z"/><path fill="#779375" d="M290 378l1 1-1-1zm-61 1l1 1-1-1z"/><path fill="#576e57" d="M216 380c-144 88-72 44 0 0z"/><path fill="#444b19" d="M274.7 381.3c-183 87-91.6 43.6 0 0z"/><path fill="#779375" d="M232.3 381.7c-155 87-77.4 43.4 0 0z"/><path fill="#95bb95" d="M211 382c-140.7 86.7-70.3 43.3 0 0z"/><path fill="#444b19" d="M273 385c-182 84.7-91 42.3 0 0z"/><path fill="#779375" d="M208 383l1 1-1-1m27 0l1 1-1-1m1 1l1 1-1-1"/><path fill="#576e57" d="M162 385l1 1-1-1z"/><path fill="#444b19" d="M238 385l1 1-1-1zm1 1l1 1-1-1m33 0l1 1-1-1"/><path fill="#9fc79f" d="M137 387l1 1-1-1z"/><path fill="#779375" d="M191 387l1 1-1-1z"/><path fill="#576e57" d="M240 387l1 1-1-1m1 1l1 1-1-1m1 1l1 1-1-1m-106 1l1 1-1-1m107 0l1 1-1-1z"/><path fill="#9fc79f" d="M136 391l1 1-1-1z"/><path fill="#576e57" d="M244 391l1 1-1-1m2 3l1 1z"/><path fill="#779375" d="M155 395l1 1-1-1z"/><path fill="#444b19" d="M251 403l1 1-1-1z"/><path fill="#576e57" d="M365 406c-1 6.8 1.4 18.2-1.5 24.2-7.2 15.3-24.4 25.4-38.5 33.7-6.6 3-13.2 7-21 5-16.8-6-21-26-35-34 0 9 .3 16 3.7 25 17.6 42 71.5 11 89.5-14 7.4-11 13.3-30 2.8-40m-208 3l1 1-1-1z"/><path fill="#779375" d="M268 416l1 1-1-1zm-15 9l1 1z"/><path fill="#444b19" d="M274 426l1 1z"/><path fill="#779375" d="M275 427l1 1-1-1zm3 4l1 1-1-1z"/><path fill="#576e57" d="M155 432c2.6 11 11 20.8 17.3 30 2 3.3 4.5 8.6 8 10.4 4.6 2.4 11.7 2.2 16.7 2.8 15.3 1.8 33.3 2.6 48-2.5 5.6-2 11.8-4 14.7-9.7 3-5.7-.6-14-1.7-20-5.6 6-9.4 12.4-16 17.5-14.2 11-43 17.8-59 6-12.4-9-17.4-24.2-28-34.5m11 0l1 1-1-1m113 0l1 1-1-1z"/><path fill="#444b19" d="M362 432l1 1-1-1z"/><path fill="#576e57" d="M167 433l1 1-1-1zm182 0l1 1-1-1z"/><path fill="#444b19" d="M280 434l1 1-1-1m1 1l1 1-1-1z"/><path fill="#576e57" d="M282 436l1 1-1-1z"/><path fill="#444b19" d="M169 437l1 1-1-1zm188 0l1 1-1-1z"/><path fill="#779375" d="M170 438l1 1-1-1"/><path fill="#444b19" d="M356 438l1 1-1-1m-186 1l1 1-1-1z"/><path fill="#576e57" d="M284 439l1 1-1-1z"/><path fill="#444b19" d="M355 439l1 1-1-1m-197 1l1 1-1-1m13 0l1 1-1-1z"/><path fill="#576e57" d="M248 440l1 1-1-1z"/><path fill="#444b19" d="M285 440l1 1-1-1z"/><path fill="#779375" d="M343 440l1 1-1-1z"/><path fill="#444b19" d="M354 440l1 1-1-1m-11 1l1 1-1-1m-54 4l1 1-1-1m-30 7c-172.7 40-86.3 20 0 0z"/><path fill="#576e57" d="M290 446l1 1-1-1zm-54 7l1 1-1-1m90 0l1 1-1-1z"/><path fill="#444b19" d="M341 453l1 1-1-1zm-44 1l1 1-1-1zm58 0l1 1-1-1z"/><path fill="#576e57" d="M233 455l1 1-1-1z"/><path fill="#444b19" d="M248 455l1 1-1-1m38 0l1 1-1-1m12 0l1 1-1-1z"/><path fill="#576e57" d="M320 456l1 1-1-1z"/><path fill="#444b19" d="M321 456l1 1-1-1z"/><path fill="#779375" d="M229 457l1 1-1-1z"/><path fill="#444b19" d="M288 457l1 1-1-1z"/><path fill="#779375" d="M319 457l1 1-1-1z"/><path fill="#444b19" d="M289 458l1 1z"/><path fill="#9fc79f" d="M375 459l1 1-1-1z"/><path fill="#576e57" d="M200 462c-133.3 33.3-66.7 16.7 0 0z"/></svg> diff --git a/static/pix/jitsi-01.webp b/static/pix/jitsi-01.webp Binary files differnew file mode 100644 index 0000000..a71f1ae --- /dev/null +++ b/static/pix/jitsi-01.webp diff --git a/static/pix/jitsi.svg b/static/pix/jitsi.svg new file mode 100644 index 0000000..5a3526a --- /dev/null +++ b/static/pix/jitsi.svg @@ -0,0 +1,650 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg5488" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="New document 5"> + <defs + id="defs5490"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective5496" /> + <inkscape:perspective + id="perspective5347" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient8896" + id="linearGradient4242" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="439.90353" + y1="455.73935" + x2="469.71744" + y2="557.74847" /> + <linearGradient + id="linearGradient8896"> + <stop + id="stop8898" + offset="0" + style="stop-color:#0f3060;stop-opacity:1;" /> + <stop + style="stop-color:#0575ce;stop-opacity:1;" + offset="0.27115166" + id="stop8902" /> + <stop + id="stop12553" + offset="0.7327472" + style="stop-color:#0575ce;stop-opacity:1;" /> + <stop + style="stop-color:#0f3060;stop-opacity:1;" + offset="1" + id="stop8900" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5041" + id="linearGradient4244" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="382.80234" + y1="585.22589" + x2="347.44287" + y2="645.02435" /> + <linearGradient + id="linearGradient5041"> + <stop + style="stop-color:#092d61;stop-opacity:1;" + offset="0" + id="stop5043" /> + <stop + id="stop5047" + offset="1" + style="stop-color:#0575ce;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3493" + id="linearGradient4246" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="415.81378" + y1="620.09808" + x2="436.35599" + y2="486.43097" /> + <linearGradient + id="linearGradient3493"> + <stop + style="stop-color:#0f3060;stop-opacity:1;" + offset="0" + id="stop3495" /> + <stop + id="stop3497" + offset="0.45698157" + style="stop-color:#0575ce;stop-opacity:1;" /> + <stop + style="stop-color:#0575ce;stop-opacity:1;" + offset="0.73828435" + id="stop3501" /> + <stop + id="stop3507" + offset="1" + style="stop-color:#0f3060;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3529" + id="linearGradient4248" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="389.59329" + y1="763.3017" + x2="308.98642" + y2="420.01578" /> + <linearGradient + id="linearGradient3529"> + <stop + id="stop3531" + offset="0" + style="stop-color:#ff8000;stop-opacity:1;" /> + <stop + style="stop-color:#fff4e1;stop-opacity:1;" + offset="0.6627211" + id="stop3533" /> + <stop + id="stop3535" + offset="0.75" + style="stop-color:#fff4e1;stop-opacity:1;" /> + <stop + id="stop3537" + offset="1.0000000" + style="stop-color:#ff8400;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3591" + id="linearGradient4250" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="528.82031" + y1="511.71811" + x2="458.46918" + y2="527.10736" /> + <linearGradient + id="linearGradient3591"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3593" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3595" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7434" + id="linearGradient4252" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="197.17841" + y1="703.80151" + x2="146.54216" + y2="785.90436" /> + <linearGradient + id="linearGradient7434"> + <stop + id="stop7436" + offset="0" + style="stop-color:#ffc768;stop-opacity:1;" /> + <stop + style="stop-color:#ff8400;stop-opacity:1.0000000;" + offset="0.37842149" + id="stop7438" /> + <stop + id="stop7440" + offset="0.77420431" + style="stop-color:#ff8400;stop-opacity:1.0000000;" /> + <stop + id="stop7442" + offset="1" + style="stop-color:#ffc768;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3591" + id="linearGradient4254" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0334058,0,0,1.0138319,-309.91012,314.18347)" + x1="413.63229" + y1="484.60083" + x2="423.52518" + y2="541.83301" /> + <linearGradient + id="linearGradient5384"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop5386" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop5388" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3509" + id="linearGradient4256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="409.69571" + y1="559.36359" + x2="467.88617" + y2="676.03516" /> + <linearGradient + id="linearGradient3509"> + <stop + id="stop3511" + offset="0" + style="stop-color:#ff8000;stop-opacity:1;" /> + <stop + style="stop-color:#ffc768;stop-opacity:1.0000000;" + offset="0.34144846" + id="stop3513" /> + <stop + id="stop3515" + offset="0.71198046" + style="stop-color:#ffc768;stop-opacity:1.0000000;" /> + <stop + id="stop3517" + offset="1.0000000" + style="stop-color:#ff8400;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3651" + id="linearGradient4258" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="522.63641" + y1="168.68723" + x2="585.93317" + y2="161.10866" /> + <linearGradient + id="linearGradient3651"> + <stop + style="stop-color:#ff8000;stop-opacity:1;" + offset="0" + id="stop3653" /> + <stop + id="stop16786" + offset="0.5" + style="stop-color:#fff4e1;stop-opacity:1;" /> + <stop + style="stop-color:#fff4e1;stop-opacity:1;" + offset="0.75" + id="stop17514" /> + <stop + style="stop-color:#ff8400;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3655" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3509" + id="linearGradient4260" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="481.48975" + y1="417.49979" + x2="405.41116" + y2="316.78976" /> + <linearGradient + id="linearGradient5403"> + <stop + id="stop5405" + offset="0" + style="stop-color:#ff8000;stop-opacity:1;" /> + <stop + style="stop-color:#ffc768;stop-opacity:1.0000000;" + offset="0.34144846" + id="stop5407" /> + <stop + id="stop5409" + offset="0.71198046" + style="stop-color:#ffc768;stop-opacity:1.0000000;" /> + <stop + id="stop5411" + offset="1.0000000" + style="stop-color:#ff8400;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3591" + id="linearGradient4262" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="473.09195" + y1="499.58444" + x2="457.68967" + y2="477.5997" /> + <linearGradient + id="linearGradient5414"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop5416" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop5418" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3591" + id="linearGradient4264" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="394.34113" + y1="501.80154" + x2="446.31302" + y2="485.37762" /> + <linearGradient + id="linearGradient5421"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop5423" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop5425" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3591" + id="linearGradient4266" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-297.23084,320.86007)" + x1="395.81326" + y1="590.73315" + x2="369.55322" + y2="572.16907" /> + <linearGradient + id="linearGradient5428"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop5430" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop5432" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2937" + id="linearGradient4268" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,34.35214,723.04037)" + x1="297.05316" + y1="667.16193" + x2="310.45529" + y2="713.86633" /> + <linearGradient + id="linearGradient2937"> + <stop + style="stop-color:#212a3a;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop2939" /> + <stop + style="stop-color:#404e67;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop2941" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2937" + id="linearGradient4270" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.09307993,0,0,0.1860535,131.94157,665.87199)" + x1="246.30438" + y1="690.02673" + x2="366.87921" + y2="632.15985" /> + <linearGradient + id="linearGradient5439"> + <stop + style="stop-color:#212a3a;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5441" /> + <stop + style="stop-color:#404e67;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop5443" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2937" + id="linearGradient4272" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.09281332,-0.00703915,0.01407026,-0.1855207,186.19996,929.70821)" + x1="301.05194" + y1="645.89917" + x2="367.94604" + y2="654.72131" /> + <linearGradient + id="linearGradient5446"> + <stop + style="stop-color:#212a3a;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5448" /> + <stop + style="stop-color:#404e67;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop5450" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2937" + id="linearGradient4274" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,98.31046,642.63728)" + x1="279.81714" + y1="688.32355" + x2="386.78625" + y2="667.6355" /> + <linearGradient + id="linearGradient5453"> + <stop + style="stop-color:#212a3a;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5455" /> + <stop + style="stop-color:#404e67;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop5457" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2937" + id="linearGradient4276" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.245729,0,0,0.245729,25.55056,660.77045)" + x1="338.14404" + y1="668.3009" + x2="266.215" + y2="702.89276" /> + <linearGradient + id="linearGradient5460"> + <stop + style="stop-color:#212a3a;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5462" /> + <stop + style="stop-color:#404e67;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop5464" /> + </linearGradient> + <linearGradient + y2="702.89276" + x2="266.215" + y1="668.3009" + x1="338.14404" + gradientTransform="matrix(0.245729,0,0,0.245729,25.55056,660.77045)" + gradientUnits="userSpaceOnUse" + id="linearGradient5486" + xlink:href="#linearGradient2937" + inkscape:collect="always" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.35" + inkscape:cx="375" + inkscape:cy="520" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="798" + inkscape:window-height="690" + inkscape:window-x="20" + inkscape:window-y="20" + inkscape:window-maximized="0" /> + <metadata + id="metadata5493"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + id="g4202" + transform="matrix(4.2070673,0,0,4.2070673,-152.93197,-3059.7049)"> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csssssssssssssssssssssssssssssssssccssssssssssccsssssssssccsssssssssscssssssssssccssssssscssssssssc" + id="path4204" + d="m 52.51386,963.95968 c -0.59762,-1.31419 -1.08659,-2.49776 -1.08659,-2.63031 0,-0.13252 -2.08061,-11.07486 -2.31769,-13.88681 -1.03506,-12.27691 -2.66752,-13.45265 -2.21175,-24.39857 0.2761,-6.63061 -0.64392,-8.89235 1.31344,-14.31478 4.03102,-11.16694 6.98662,-15.56085 12.2251,-18.17414 4.24974,-2.12004 8.23695,-1.83207 11.97929,0.86518 0.98634,0.71092 4.29577,2.95048 7.35426,4.97678 3.05851,2.02634 6.69103,4.48296 8.07229,5.45919 1.38125,0.97628 3.68511,2.38497 5.11972,3.13046 2.53058,1.3151 2.62411,1.3351 3.13729,0.67104 1.12761,-1.45907 3.84947,-5.55395 5.32124,-7.50854 7.37209,-9.79052 0.42914,-8.70222 -1.30592,-9.21291 -2.72783,-0.80294 -3.87684,-1.97938 -6.42642,-4.96758 -5.92163,-6.94035 -8.72797,-14.66214 -9.14262,-24.20339 -0.48154,-11.07972 0.63266,-20.01531 5.49789,-25.10088 2.08527,-2.17973 6.49949,-5.34524 10.53505,-7.55495 3.4177,-1.87139 24.37883,-5.78232 26.21837,-4.96975 0.91898,0.40593 -3.63796,-11.63862 -1.01552,-27.29896 0.52096,-3.11103 4.05934,-12.73788 4.43322,-13.39298 0.92313,-1.61744 16.13503,-6.82395 20.46221,-9.36515 4.83486,-2.83935 15.29074,-9.67883 16.07843,-14.76568 1.73099,-11.1786 2.03825,-15.9556 2.75981,-16.37531 1.07388,-0.62465 8.25251,14.17566 3.39352,28.13116 -0.95893,2.75414 -5.53206,9.14865 -7.57975,11.8233 -1.47452,1.92602 1.72775,2.82621 3.56985,5.60679 1.67534,2.52882 2.77675,8.71086 2.9918,11.91416 0.21959,3.27101 -0.81543,9.98235 -1.7425,11.2988 -0.37549,0.53325 -0.52929,1.05709 -0.34387,1.17136 0.18449,0.11368 1.43417,-0.0352 2.77708,-0.33076 1.34289,-0.29559 4.25366,-0.7663 6.46837,-1.046 3.94259,-0.49787 4.08384,-0.49095 6.7595,0.33213 4.01386,1.23476 23.53789,5.95177 11.07947,60.50742 -4.12753,18.07453 -23.38873,41.92489 -25.8106,40.0783 l -5.96407,-4.5474 -6.87325,10.19022 c -3.50798,3.60293 -7.29065,7.08029 -9.52167,8.75312 -3.52051,2.63972 -10.56453,6.79799 -11.51562,6.79799 -0.24492,0 -1.63251,0.56931 -3.08354,1.26516 -4.19508,2.01176 -10.47851,3.66081 -17.13429,4.09795 -25.77135,1.66956 -15.93975,-1.44192 -37.27858,-11.77515 -1.68316,-0.81506 -5.55753,3.29679 -10.22719,7.54571 -4.98524,4.53606 -7.60226,7.98846 -9.57996,12.63792 -0.66947,1.57389 -1.71168,3.98838 -2.31602,5.36552 -1.64444,3.74731 -2.99719,8.93229 -3.19818,12.25814 -0.0983,1.62685 -0.31514,3.04193 -0.48187,3.14469 -0.16673,0.10272 -0.7921,-0.88841 -1.38973,-2.20249 z m 28.33197,-45.90886 c 3.30313,-0.83536 3.66477,-1.01966 7.21765,-3.67825 2.54576,-1.90501 4.12321,-5.3446 4.8004,-5.64508 4.4324,-1.96673 -3.3083,-3.73691 -6.20226,-5.68891 -2.89398,-1.95202 -6.65724,-3.39508 -9.2209,-5.3521 -2.56367,-1.95698 -4.78356,-3.48279 -4.93308,-3.39068 -0.14952,0.0921 -0.27471,1.40551 -0.27821,2.91861 -0.01023,4.41323 -0.6021,8.84164 -1.42935,10.69448 -0.42105,0.94301 -0.84611,2.76087 -0.94461,4.03969 -0.22816,2.96221 0.46109,4.38683 2.91271,6.02036 2.06595,1.3766 2.92385,1.38532 8.07765,0.0819 z m 119.70575,-83.58495 c -1.07558,-7.22468 -0.18498,-17.16053 -5.81444,-20.77728 -12.98767,-8.34415 -14.4135,-0.0696 -15.21021,1.75899 -1.31072,3.0083 -2.11753,5.46892 -1.12273,8.7761 3.05641,10.16086 6.96643,19.15821 8.82255,26.38029 2.13021,8.28856 4.47797,13.53077 4.71288,20.02986 0.16678,4.61378 0.12302,5.09887 -0.55601,6.16474 -0.9655,1.51542 -15.55215,5.22752 -22.89767,7.39176 -2.52211,0.74311 -0.28804,6.12175 -0.57696,7.89239 -0.28892,1.77059 -4.23701,11.66713 -2.96729,13.65682 12.52923,19.63374 40.23506,-40.20634 35.60988,-71.27367 z m -26.98831,48.27201 c 1.95984,-0.47131 3.79219,-1.04626 4.0719,-1.27773 0.27971,-0.23143 0.99066,-0.38419 1.57991,-0.33941 1.05432,0.0801 5.18218,-1.21949 5.4995,-1.73148 0.0894,-0.14415 3.7722,-2.06556 3.0355,-2.55357 -0.73674,-0.48803 -15.13237,-11.07005 -17.19649,-12.14627 -23.77004,-12.39364 -36.26526,-13.24685 -44.11407,-11.66556 -13.44457,2.70866 -25.05657,9.52598 -26.45346,11.20755 -0.42178,0.50774 21.04913,-6.66097 36.28977,0.87085 2.81591,1.39161 8.62965,3.78304 13.00058,8.46269 3.99268,4.27467 7.63329,8.79778 10.49869,9.5617 3.10695,0.82834 9.47337,0.64882 13.78817,-0.38877 z m -28.65731,-51.09687 c 7.52619,-1.317 19.18627,-16.95235 18.27894,-18.41606 -0.12276,-0.19808 2.25527,-4.14459 1.86904,-4.22161 -14.0842,-2.80833 -13.74485,-16.83242 -13.94793,-16.95753 -0.20308,-0.12514 -20.76525,9.71022 -25.50376,11.75869 -4.02092,1.73825 0.57503,12.10208 2.99929,18.53437 1.07855,2.86172 7.01744,6.67785 9.40766,8.23365 2.82773,1.84055 6.25378,1.181 6.89676,1.06849 z m 16.21969,-47.71727 c 4.06405,-3.20289 14.88802,-19.23422 13.73961,-25.73988 -4.67874,-26.5048 -6.69569,-10.0962 -6.99598,-7.73088 -0.12436,0.97963 -0.47868,3.14936 -0.7874,4.82161 -0.30868,1.67227 -0.70224,4.08678 -0.87456,5.36555 -0.1723,1.2788 -0.64865,3.53233 -1.05855,5.00784 -0.4099,1.47554 -1.05724,3.92831 -1.43856,5.45066 -0.38128,1.52232 -1.66486,5.27236 -2.85234,8.33339 -1.18749,3.06104 -2.15908,5.63846 -2.15908,5.72759 0,0.447 0.82393,0.0274 2.42686,-1.23588 z" + style="fill:url(#linearGradient4242);fill-opacity:1" /> + <path + sodipodi:nodetypes="ccssc" + id="path4206" + d="m 53.57922,963.11994 c 6.35309,-26.31992 12.10112,-29.26957 27.22751,-39.0261 -3.32781,-1.89079 -11.51745,-8.1594 -11.49606,-11.49606 0.05726,-9.74197 1.6676,-26.72201 -9.07584,-19.66431 -20.38515,13.39167 -13.0087,55.96766 -6.65561,70.18647 z" + style="fill:url(#linearGradient4244);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + sodipodi:nodetypes="ccccsc" + id="path4208" + d="m 75.93257,920.7226 c 8.98173,6.78619 16.91991,12.78559 22.55412,15.96751 54.94138,2.77762 68.66033,-27.59386 69.6583,-52.49321 -4.89006,0.22454 -13.22311,-0.97302 -17.71397,-7.7405 -11.21439,3.68089 -45.16617,14.00314 -45.75692,16.32304 -3.06467,12.03515 -12.17523,21.75574 -28.74153,27.94316 z" + style="fill:url(#linearGradient4246);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="cssssss" + id="path4210" + d="m 171.27539,910.58112 c 33.18508,-24.69965 28.91369,-74.159 29.44979,-76.69151 1.36299,-6.43866 -6.64955,-28.25155 -16.27383,-24.24947 -16.02424,6.66336 11.2767,44.44456 7.61407,65.1661 -0.76342,4.31907 -13.98948,7.50294 -22.98022,8.89864 -1.03689,0.16096 -0.1163,14.0955 -4.62673,20.50927 -0.64571,0.91818 6.21023,6.81854 6.81692,6.36697 z" + style="fill:url(#linearGradient4248);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + sodipodi:nodetypes="ccc" + id="path4212" + d="m 175.90353,907.19115 c 42.49251,-41.74886 20.98218,-116.27813 6.14636,-94.50993 20.37687,-4.1207 23.61854,64.2671 -6.14636,94.50993 z" + style="fill:url(#linearGradient4250);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csszs" + id="path4214" + d="m 95.21705,907.77562 c 0.78602,-1.06057 -13.88152,-6.08284 -22.74639,-14.06472 -0.98292,-0.88501 -1.14144,12.91242 -2.0703,18.66551 -0.57712,3.57451 5.4925,7.17351 6.87977,7.62184 1.15081,0.37191 14.71014,-7.86884 17.93692,-12.22263 z" + style="fill:url(#linearGradient4252);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + sodipodi:nodetypes="ccccc" + id="path4216" + d="m 83.58536,868.01334 c -5.099007,-25.84347 4.179267,-41.03939 41.3579,-46.37791 0.18024,0.56879 41.31909,-13.25606 55.79189,-13.35001 -3.92283,6.23323 0.0433,21.62385 4.80916,34.27609 0,0 -34.8276,9.08768 -101.95895,25.45183 z" + style="fill:url(#linearGradient4254);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csssss" + id="path4218" + d="m 101.65537,863.89391 c 4.41182,-1.58073 17.00722,-5.39035 32.05421,-0.1519 10.3057,3.58781 16.2195,12.63312 20.66816,16.112 10.4789,8.19457 29.82289,-0.90843 33.32172,-0.85341 1.43753,0.0226 -25.96694,-24.60193 -46.62844,-25.8478 -27.77538,-1.67482 -45.11147,12.78188 -39.41565,10.74111 z" + style="fill:url(#linearGradient4256);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csss" + id="path4220" + d="m 169.42704,741.43522 c -0.1528,8.40398 -2.79669,28.46338 -11.30718,42.1727 -3.89274,6.27072 14.52008,-8.27661 16.50236,-20.78075 1.09029,-6.8775 -5.06881,-28.08959 -5.19518,-21.39195 z" + style="fill:url(#linearGradient4258);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="cssscsc" + id="path4222" + d="m 141.79058,833.10697 c 9.23931,-4.71783 17.65654,-10.92192 22.99128,-22.44259 0.9032,-1.9505 -4.39968,-0.0586 -8.47555,-5.84433 -4.0357,-5.72867 -3.08341,-11.54295 -6.54001,-11.07789 -10.80021,1.4531 -25.20082,11.63758 -25.20082,11.63758 0,0 0.82824,11.14408 3.74751,15.67372 6.01898,9.33928 13.47759,12.05351 13.47759,12.05351 z" + style="fill:url(#linearGradient4260);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + sodipodi:nodetypes="ccc" + id="path4224" + d="m 156.09152,803.78111 c 2.72579,9.88879 17.87347,8.09668 14.70668,-11.15251 -1.36528,1.99619 -4.77608,12.95694 -14.70668,11.15251 z" + style="opacity:0.55223843;fill:url(#linearGradient4262);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + sodipodi:nodetypes="csccsc" + id="path4226" + d="m 140.48504,832.28297 c -5.10096,-3.46887 -9.50419,-7.78444 -12.32504,-12.34966 -2.82085,-4.56521 -4.0593,-27.84724 0.68685,-33.63375 2.60826,-6.3637 11.84132,-12.51424 22.09721,-15.2308 -19.49494,22.60506 -13.17796,56.86685 4.07359,53.53526 0.86206,-0.16648 -12.82587,7.73026 -14.53261,7.67895 z" + style="fill:url(#linearGradient4264);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + sodipodi:nodetypes="ccc" + id="path4228" + d="m 72.32239,893.02911 c 3.80886,2.81881 20.23882,15.53557 23.85984,13.52306 -8.41018,20.55895 -30.55349,3.14238 -23.85984,-13.52306 z" + style="fill:url(#linearGradient4266);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="ccsssccssscccsssscscsccsssssccssssssccsssccssssccsscssssssssssssccsssccssssssccssssssssssssscsssscssscssc" + id="path4230" + d="m 140.05745,777.56053 c -3.94728,2.30056 -8.69302,4.87373 -9.63531,7.20019 -3.16217,6.64336 -4.34745,18.56552 -3.38465,17.88089 9.38401,-6.67285 20.24871,-8.52283 24.20205,-12.0967 11.71489,-10.59045 16.26287,-32.48353 13.80119,-29.2383 -7.96915,10.50564 -20.9111,13.88057 -24.98328,16.25392 z m -61.4085,147.01185 c 0,0 -11.08091,-7.66436 -10.87669,-10.1233 1.697,-20.4327 -1.92942,-21.625 -3.75706,-21.40828 -2.20803,0.26184 -13.6822,7.50553 -15.92058,27.95835 -1.62427,14.84147 4.24013,38.0296 5.13347,39.28426 4.62276,-12.42378 2.81919,-22.42331 25.42086,-35.71103 z m 121.05779,-90.52225 c -0.55133,-15.31772 -9.77382,-25.84979 -16.03746,-23.38322 -2.65737,1.04645 -4.4415,8.17887 -3.50846,12.60125 0.82755,3.92256 6.46634,19.10152 6.87179,20.38471 0.95868,3.03418 7.43087,21.62978 6.28035,30.56471 -1.00846,7.8316 -23.7097,10.5413 -23.7097,10.5413 0,0 -0.38149,6.37449 -1.16407,10.68177 -0.96202,5.29492 -2.86934,9.45033 -2.86934,9.45033 0,0 4.94251,4.60429 5.14224,4.59918 0.19973,-0.005 31.10844,-16.7127 28.99465,-75.44003 z m -23.69666,47.44964 c 1.59781,-0.44722 11.03201,-2.94175 10.52638,-3.27341 -3.50095,-2.2964 -7.48504,-5.18714 -14.1578,-10.37693 -37.04552,-28.81248 -70.69468,-4.54502 -70.03165,-4.76554 6.15153,-2.04594 12.64754,-3.20211 21.67232,-2.5993 7.26918,0.48555 18.69619,4.17029 28.70607,16.10244 3.72328,4.43828 7.94798,7.4497 23.28468,4.91274 z M 159.4851,818.95922 c 1.12085,-0.96962 5.01656,-8.31336 4.31505,-8.48395 -9.83076,-2.39074 -10.78824,-6.74031 -11.75043,-11.4727 -0.90123,-4.43254 -0.76219,-5.06465 -2.62452,-4.44953 -15.04703,4.96997 -19.20919,7.70131 -21.51157,9.61214 -3.60666,2.99331 -1.0768,11.03634 0.33349,14.23298 1.96563,4.4554 9.19232,12.51758 12.55437,13.16681 4.90391,0.94697 16.49344,-9.09974 18.68361,-12.60575 z m 10.93597,-27.14087 c -0.81548,-3.33524 -3.43538,-7.63066 -4.13349,-7.63066 -0.65744,0 -7.61876,5.38666 -9.4168,7.26354 -4.08086,4.25969 -2.09206,11.97893 2.43483,14.62671 7.66207,4.48154 13.28874,-5.37111 11.11546,-14.25959 z m -5.77705,-12.75642 c 3.35221,-3.34862 7.80844,-8.84532 8.99344,-17.19839 0.46443,-3.27384 0.73411,-6.15364 -1.30205,-12.62655 -0.47191,-1.50022 -1.90642,-5.8148 -1.96005,-5.24636 -1.05907,11.22382 -2.61083,23.68653 -9.93627,36.93167 -2.29934,4.15745 -1.06286,3.40174 4.20493,-1.86037 z m -78.6191,66.84814 c -3.99349,16.75103 6.58927,38.75062 15.16215,40.00456 8.28707,1.21213 32.04487,-5.96093 44.50484,-9.42568 3.26456,-0.90778 5.02074,-0.43427 -2.20131,-6.48455 -11.3226,-7.69755 -20.46099,-8.68868 -29.5776,-7.65392 -10.05581,1.14135 -17.59102,4.11772 -16.88606,3.52743 4.61053,-3.86056 12.8225,-10.76401 28.68812,-13.89013 6.89585,-1.35875 17.53788,-1.47808 30.38613,3.54005 15.93675,6.2244 24.23739,15.45542 30.97531,18.58381 2.39935,1.11401 3.25644,0.59604 4.20446,-2.18817 1.5883,-4.66452 -8.06663,-33.78938 -11.56456,-42.28236 -5.33802,-12.96073 0.89004,-19.15557 -0.47125,-18.85551 -6.6027,1.45543 -12.42508,5.69932 -17.306,10.06932 -11.93084,10.68198 -19.20273,12.95753 -20.28189,12.86579 -3.40727,-0.28972 -9.78249,-6.32022 -12.09877,-9.38241 -1.47795,-1.95389 -27.92949,3.15177 -35.72972,9.92827 -0.17845,0.15503 -6.19704,4.01498 -7.80385,11.6435 z M 77.5498,918.8389 c 8.72435,-3.6605 17.26585,-11.43939 16.52709,-11.56787 -4.52939,-0.78772 -21.23379,-12.23383 -21.22226,-12.11514 0.57378,5.90697 -0.71357,11.21473 -1.30092,17.06944 -0.24494,2.44161 3.00975,6.22428 5.99609,6.61357 z m 28.15174,-25.60492 c -1.66901,3.72058 -3.41156,18.3512 -27.53028,27.73991 -0.69864,0.27195 20.21205,14.57036 21.35002,14.62032 69.0544,3.03144 68.46916,-49.55437 67.5526,-50.88016 -0.13265,-0.19188 -6.03889,0.0138 -10.61352,-2.15692 -0.34887,-0.1655 -3.45204,-1.76502 -5.30227,-4.17423 -0.62757,-0.81715 -0.72524,-1.26122 -3.05074,-0.58541 -10.76269,3.12776 -42.89539,14.65696 -42.40581,15.43649 z M 84.18935,867.5847 c -12.33127,-43.08647 30.94329,-45.08535 37.80451,-46.74439 5.30593,-1.28297 4.14977,-1.78189 3.03089,-6.80033 -1.57099,-7.04629 -1.0816,-13.18841 0.26513,-19.77217 1.27351,-6.2258 1.93035,-9.37394 4.61998,-12.49571 2.16789,-2.51621 14.38379,-8.27049 17.4121,-9.72295 12.90529,-6.18974 17.83586,-12.99328 19.27422,-18.34465 1.014,-3.77255 2.49779,-13.07094 1.83081,-19.71727 -0.16416,-1.6359 0.89135,0.92745 6.14205,17.24159 2.68293,8.33593 1.36177,18.34502 -7.09994,27.38172 -1.14918,1.22726 -0.59185,1.4703 0.95354,4.02388 3.21078,5.30554 4.98573,11.93993 4.48566,16.76662 -0.40972,3.95432 -2.10008,7.6934 0.31754,7.40286 0.34951,-0.042 11.02834,-1.65875 18.33848,2.98757 4.95048,3.14653 12.00258,9.17808 10.17204,34.37342 -4.00842,55.17187 -30.9649,67.17892 -31.15387,67.18542 -0.4563,0.0156 -5.49956,-5.22074 -5.79806,-4.60407 -15.45677,31.93103 -47.3506,30.78387 -65.13826,31.11951 -3.55635,0.0671 -18.34444,-12.38469 -19.59088,-11.53286 -15.74294,10.75882 -20.11352,13.44589 -26.18374,40.94381 -0.23264,-0.43595 -8.41803,-14.95561 -8.07826,-44.15673 0.27838,-23.92523 13.34923,-35.21616 19.15997,-34.56498 7.05422,0.79055 10.59443,4.47084 20.52923,10.99795 1.77335,1.16509 8.0388,4.95377 9.46457,4.91926 3.5521,-0.0838 5.97534,-6.60969 6.55509,-10.83484 0.58475,-4.26168 1.15009,-3.23167 -2.17605,-4.37633 -4.1934,-1.44311 -11.42652,-9.296 -15.13675,-21.67633 z" + style="fill:#2c3b54;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="czssss" + id="path4232" + d="m 106.11345,892.83442 c 6.47531,-3.53335 43.23312,-15.02538 43.56314,-15.74675 0.24089,-0.52655 -43.11579,17.30875 -52.93537,10.69734 -0.59185,-0.39849 2.29344,1.72127 4.90219,2.25652 0.18326,0.0376 0.17092,6.89208 -2.30068,10.77041 -0.6931,1.08758 5.26729,-7.15715 6.77072,-7.97752 z" + style="fill:url(#linearGradient4268);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csss" + id="path4234" + d="m 166.00752,784.18642 c -4.02929,2.81265 -9.5846,6.74255 -10.72057,9.77333 -0.66996,1.78745 -1.12247,-4.99153 3.45182,-9.03009 2.57716,-2.27533 8.09315,-1.31871 7.26875,-0.74324 z" + style="fill:url(#linearGradient4270);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csss" + id="path4236" + d="m 160.58968,806.82846 c 4.57007,1.3627 8.10001,-1.42847 10.03503,-7.4422 0.22874,-0.71087 -0.56553,5.2666 -3.40562,7.48857 -2.70767,2.11837 -7.59288,-0.33365 -6.62941,-0.0464 z" + style="fill:url(#linearGradient4272);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="cscss" + id="path4238" + d="m 172.18948,813.03639 c 6.47531,-3.53335 13.10498,-2.9926 18.75586,-2.73805 3.75103,0.16896 -7.06591,-4.20527 -19.35477,-3.52147 -1.31254,1.11755 -5.21285,7.63595 -10.70973,14.23704 -0.82526,0.99104 9.80521,-7.15715 11.30864,-7.97752 z" + style="fill:url(#linearGradient4274);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + <path + inkscape:export-ydpi="19.25" + inkscape:export-xdpi="19.25" + inkscape:export-filename="/home/emcho/storage/images/sc_logo/sc_logo136x203.png" + sodipodi:nodetypes="csccscs" + id="path4240" + d="m 110.55877,827.01111 c 3.80202,-0.78266 8.57073,-2.07478 11.72698,-2.39299 2.63172,-0.26532 5.92925,-1.74739 8.46259,0.97744 -1.41052,-1.93357 -4.10815,-5.83882 -4.94871,-8.39667 0.76528,3.00553 -2.65492,3.42931 -3.50504,3.56438 -19.11709,3.02037 -30.61745,8.16849 -36.41981,17.74206 10.99033,-8.50263 23.96641,-11.34651 24.68399,-11.49422 z" + style="fill:url(#linearGradient5486);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" /> + </g> + </g> +</svg> diff --git a/static/pix/landchad.gif b/static/pix/landchad.gif Binary files differnew file mode 100644 index 0000000..302cd26 --- /dev/null +++ b/static/pix/landchad.gif diff --git a/static/pix/matrix.svg b/static/pix/matrix.svg new file mode 100644 index 0000000..9a8b8dd --- /dev/null +++ b/static/pix/matrix.svg @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="793.322px" height="340.809px" viewBox="0 0 793.322 340.809" fill="#fff" enable-background="new 0 0 793.322 340.809" + xml:space="preserve"> +<path d="M10.875,9.711v321.386h23.13v7.711H1.999V2.001h32.006v7.71H10.875z"/> +<path d="M99.988,111.595v16.264h0.463c4.338-6.191,9.563-10.998,15.684-14.406c6.117-3.402,13.129-5.11,21.027-5.11 + c7.588,0,14.521,1.475,20.793,4.415c6.274,2.945,11.038,8.131,14.291,15.567c3.56-5.265,8.4-9.913,14.521-13.94 + c6.117-4.025,13.358-6.042,21.724-6.042c6.351,0,12.234,0.776,17.66,2.325c5.418,1.549,10.065,4.027,13.938,7.434 + c3.869,3.41,6.889,7.863,9.062,13.357c2.167,5.504,3.253,12.122,3.253,19.869v80.385H219.41v-68.074 + c0-4.025-0.154-7.82-0.465-11.385c-0.313-3.56-1.161-6.656-2.555-9.293c-1.395-2.631-3.45-4.724-6.157-6.274 + c-2.711-1.543-6.391-2.322-11.037-2.322s-8.403,0.896-11.269,2.671c-2.868,1.784-5.112,4.109-6.737,6.971 + c-1.626,2.869-2.711,6.12-3.252,9.762c-0.545,3.638-0.814,7.318-0.814,11.035v66.91h-32.991v-67.375c0-3.562-0.081-7.087-0.23-10.57 + c-0.158-3.487-0.814-6.7-1.978-9.645c-1.162-2.94-3.099-5.304-5.809-7.088c-2.711-1.775-6.699-2.671-11.965-2.671 + c-1.551,0-3.603,0.349-6.156,1.048c-2.556,0.697-5.036,2.016-7.435,3.949c-2.404,1.938-4.454,4.726-6.158,8.363 + c-1.705,3.642-2.556,8.402-2.556,14.287v69.701h-32.99V111.595H99.988z"/> +<path d="M273.544,129.255c3.405-5.113,7.744-9.215,13.012-12.316c5.264-3.097,11.186-5.303,17.771-6.621 + c6.582-1.315,13.205-1.976,19.865-1.976c6.042,0,12.158,0.428,18.354,1.277c6.195,0.855,11.85,2.522,16.962,4.997 + c5.111,2.477,9.292,5.926,12.546,10.338c3.253,4.414,4.879,10.262,4.879,17.543v62.494c0,5.428,0.31,10.611,0.931,15.567 + c0.615,4.959,1.701,8.676,3.251,11.153H347.66c-0.621-1.86-1.126-3.755-1.511-5.693c-0.39-1.933-0.661-3.908-0.813-5.923 + c-5.267,5.422-11.465,9.217-18.585,11.386c-7.127,2.163-14.407,3.251-21.842,3.251c-5.733,0-11.077-0.698-16.033-2.09 + c-4.958-1.395-9.293-3.562-13.01-6.51c-3.718-2.938-6.622-6.656-8.713-11.147s-3.138-9.84-3.138-16.033 + c0-6.813,1.199-12.43,3.604-16.84c2.399-4.417,5.495-7.939,9.295-10.575c3.793-2.632,8.129-4.607,13.01-5.923 + c4.878-1.315,9.795-2.358,14.752-3.137c4.957-0.772,9.835-1.393,14.638-1.857c4.801-0.466,9.062-1.164,12.779-2.093 + c3.718-0.929,6.658-2.282,8.829-4.065c2.165-1.781,3.172-4.375,3.02-7.785c0-3.56-0.58-6.389-1.742-8.479 + c-1.161-2.09-2.711-3.719-4.646-4.88c-1.937-1.161-4.183-1.936-6.737-2.325c-2.557-0.382-5.309-0.58-8.248-0.58 + c-6.506,0-11.617,1.395-15.335,4.183c-3.716,2.788-5.889,7.437-6.506,13.94h-32.991 + C268.199,140.794,270.132,134.363,273.544,129.255z M338.713,175.838c-2.09,0.696-4.337,1.275-6.736,1.741 + c-2.402,0.465-4.918,0.853-7.551,1.161c-2.635,0.313-5.268,0.698-7.899,1.163c-2.48,0.461-4.919,1.086-7.317,1.857 + c-2.404,0.779-4.495,1.822-6.274,3.138c-1.784,1.317-3.216,2.985-4.3,4.994c-1.085,2.014-1.626,4.571-1.626,7.668 + c0,2.94,0.541,5.422,1.626,7.431c1.084,2.017,2.558,3.604,4.416,4.765s4.025,1.976,6.507,2.438c2.475,0.466,5.031,0.698,7.665,0.698 + c6.505,0,11.537-1.082,15.103-3.253c3.561-2.166,6.192-4.762,7.899-7.785c1.702-3.019,2.749-6.072,3.137-9.174 + c0.384-3.097,0.58-5.576,0.58-7.434v-12.316C342.547,174.173,340.805,175.14,338.713,175.838z"/> +<path d="M463.825,111.595v22.072h-24.161v59.479c0,5.573,0.928,9.292,2.788,11.149c1.856,1.859,5.576,2.788,11.152,2.788 + c1.859,0,3.638-0.076,5.343-0.232c1.703-0.152,3.33-0.388,4.878-0.696v25.557c-2.788,0.465-5.887,0.773-9.293,0.931 + c-3.407,0.149-6.737,0.23-9.99,0.23c-5.111,0-9.953-0.35-14.521-1.048c-4.571-0.695-8.597-2.047-12.081-4.063 + c-3.486-2.011-6.236-4.88-8.248-8.597c-2.016-3.714-3.021-8.595-3.021-14.639v-70.859h-19.98v-22.072h19.98V75.583h32.992v36.012 + H463.825z"/> +<path d="M510.988,111.595V133.9h0.465c1.546-3.72,3.636-7.163,6.272-10.341c2.634-3.172,5.652-5.885,9.06-8.131 + c3.405-2.242,7.047-3.985,10.923-5.228c3.868-1.237,7.898-1.859,12.081-1.859c2.168,0,4.566,0.39,7.202,1.163v30.67 + c-1.551-0.312-3.41-0.584-5.576-0.814c-2.17-0.233-4.26-0.35-6.274-0.35c-6.041,0-11.152,1.01-15.332,3.021 + c-4.182,2.014-7.55,4.761-10.107,8.247c-2.555,3.487-4.379,7.55-5.462,12.198c-1.083,4.645-1.625,9.682-1.625,15.102v54.133h-32.991 + V111.595H510.988z"/> +<path d="M570.93,93.007V65.824h32.994v27.183H570.93z M603.924,111.595v120.117H570.93V111.595H603.924z"/> +<path d="M621.115,111.595h37.637l21.144,31.365l20.911-31.365h36.476l-39.496,56.226l44.377,63.892h-37.64l-25.093-37.87 + l-25.094,37.87h-36.938l43.213-63.193L621.115,111.595z"/> +<path d="M782.443,331.097V9.711h-23.13v-7.71h32.008v336.807h-32.008v-7.711H782.443z"/> +</svg> diff --git a/static/pix/monero-01.png b/static/pix/monero-01.png Binary files differnew file mode 100644 index 0000000..44f7a62 --- /dev/null +++ b/static/pix/monero-01.png diff --git a/static/pix/monero-02.png b/static/pix/monero-02.png Binary files differnew file mode 100644 index 0000000..1ef8bbc --- /dev/null +++ b/static/pix/monero-02.png diff --git a/static/pix/monero-03.png b/static/pix/monero-03.png Binary files differnew file mode 100644 index 0000000..52bebbe --- /dev/null +++ b/static/pix/monero-03.png diff --git a/static/pix/monero-04.png b/static/pix/monero-04.png Binary files differnew file mode 100644 index 0000000..228734c --- /dev/null +++ b/static/pix/monero-04.png diff --git a/static/pix/monerod/monerod-step-1.webp b/static/pix/monerod/monerod-step-1.webp Binary files differnew file mode 100644 index 0000000..382a1b8 --- /dev/null +++ b/static/pix/monerod/monerod-step-1.webp diff --git a/static/pix/monerod/monerod-step-2.webp b/static/pix/monerod/monerod-step-2.webp Binary files differnew file mode 100644 index 0000000..48255d6 --- /dev/null +++ b/static/pix/monerod/monerod-step-2.webp diff --git a/static/pix/monerod/monerod-step-3.webp b/static/pix/monerod/monerod-step-3.webp Binary files differnew file mode 100644 index 0000000..77630ec --- /dev/null +++ b/static/pix/monerod/monerod-step-3.webp diff --git a/static/pix/monerod/monerod-step-4.webp b/static/pix/monerod/monerod-step-4.webp Binary files differnew file mode 100644 index 0000000..e0d6759 --- /dev/null +++ b/static/pix/monerod/monerod-step-4.webp diff --git a/static/pix/monerod/monerod-step-5.webp b/static/pix/monerod/monerod-step-5.webp Binary files differnew file mode 100644 index 0000000..f2050a3 --- /dev/null +++ b/static/pix/monerod/monerod-step-5.webp diff --git a/static/pix/movim.svg b/static/pix/movim.svg new file mode 100644 index 0000000..9a34dd7 --- /dev/null +++ b/static/pix/movim.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg version="1.1" viewBox="0 0 240 240" id="svg23" sodipodi:docname="vectorial.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" inkscape:export-filename="/var/www/html/movim/public/theme/img/app/512.png" inkscape:export-xdpi="204.8" inkscape:export-ydpi="204.8" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview id="namedview25" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.08" inkscape:cx="119.95192" inkscape:cy="120.19231" inkscape:window-width="1920" inkscape:window-height="1025" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg23"/> + <defs id="defs15"> + <filter id="c" x="-0.14247762" y="-0.24434544" width="1.2849552" height="1.4886909"> + <feGaussianBlur stdDeviation="10.686" id="feGaussianBlur2"/> + </filter> + <linearGradient id="b" x1="40" x2="200" y1="40" y2="200" gradientUnits="userSpaceOnUse"> + <stop stop-color="#345cca" offset="0" id="stop5" style="stop-color:#5452c9;stop-opacity:1"/> + <stop stop-color="#5d47c6" offset="1" id="stop7" style="stop-color:#413fb5;stop-opacity:1"/> + </linearGradient> + <linearGradient id="a" x1="125" x2="174.95" y1="65" y2="210.1" gradientUnits="userSpaceOnUse"> + <stop stop-color="#344394" offset="0" id="stop10"/> + <stop stop-color="#7c45df" offset="1" id="stop12" style="stop-color:#5553be;stop-opacity:1"/> + </linearGradient> + </defs> + <circle cx="120" cy="120" fill="url(#b)" stroke="url(#a)" stroke-width="3" id="circle17" r="110" inkscape:export-filename="/var/www/html/movim/public/theme/img/16.png" inkscape:export-xdpi="6.8899999" inkscape:export-ydpi="6.8899999"/> + <path transform="scale(.91667)" d="m112.916 82.039c-20.51 0-37.137 16.627-37.137 37.137 0 1.594 0.10688 3.1707 0.30171 4.7118-0.29375-9e-3 -0.58624-0.0232-0.88201-0.0232-17.434-7e-5 -31.567 14.133-31.567 31.567 0 17.434 14.133 31.567 31.567 31.567h122.44c14.357 0 25.996-11.639 25.996-25.996 0-14.357-11.639-25.996-25.996-25.996-0.0468 0-0.093-2.5e-4 -0.13928 0 0.0334-0.64832 0.0696-1.293 0.0696-1.9497 0-20.51-16.627-37.137-37.137-37.137-5.7242 0-11.15 1.3077-15.992 3.6209-6.5596-10.507-18.221-17.501-31.52-17.501z" fill="#332949" opacity=".45896" filter="url(#c)" id="path19"/> + <path d="m101.59 73.35c-18.232 0-33.011 14.78-33.011 33.011 0 1.4169 0.095 2.8184 0.26819 4.1883-0.26111-8e-3 -0.5211-0.0206-0.78401-0.0206-15.497-9e-5 -28.059 12.562-28.059 28.059 0 15.497 12.563 28.059 28.059 28.059h108.83c12.762 0 23.108-10.346 23.108-23.108 0-12.762-10.346-23.108-23.108-23.108-0.0416 0-0.0827-2.2e-4 -0.1238 0 0.0297-0.57629 0.0619-1.1493 0.0619-1.7331 0-18.231-14.78-33.011-33.011-33.011-5.0882 0-9.9111 1.1624-14.215 3.2186-5.8308-9.3396-16.197-15.556-28.018-15.556z" fill="#fff" id="path21"/> +</svg>
\ No newline at end of file diff --git a/static/pix/mumble.svg b/static/pix/mumble.svg new file mode 100644 index 0000000..263b86a --- /dev/null +++ b/static/pix/mumble.svg @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="400" height="400" id="svg2" sodipodi:version="0.32" inkscape:version="0.91 r13725" version="1.0" sodipodi:docname="mumble.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" style="display:inline"> + <title id="title3169">Mumble logo</title> + <defs id="defs4"> + <linearGradient id="linearGradient4117"> + <stop style="stop-color:#000000;stop-opacity:0;" offset="0" id="stop4119"/> + <stop id="stop4125" offset="0.81720757" style="stop-color:#000000;stop-opacity:0.01960784;"/> + <stop style="stop-color:#000000;stop-opacity:0.14509804;" offset="0.89931339" id="stop4127"/> + <stop id="stop4129" offset="0.91198522" style="stop-color:#000000;stop-opacity:0.20784314;"/> + <stop style="stop-color:#000000;stop-opacity:0.25098039;" offset="0.95598048" id="stop4131"/> + <stop style="stop-color:#000000;stop-opacity:0.33333334;" offset="1" id="stop4121"/> + </linearGradient> + <linearGradient inkscape:collect="always" id="linearGradient3972"> + <stop style="stop-color:#b3b3b3;stop-opacity:1;" offset="0" id="stop3974"/> + <stop style="stop-color:#b3b3b3;stop-opacity:0;" offset="1" id="stop3976"/> + </linearGradient> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient1125-2" id="radialGradient1131-6" cx="333.52826" cy="217.58252" fx="333.52826" fy="217.58252" r="29.875" gradientTransform="matrix(-0.95122439,-0.37973408,-0.79004638,1.9790465,561.77552,-104.77634)" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" id="linearGradient1125-2"> + <stop style="stop-color:#e6e6e6;stop-opacity:1;" offset="0" id="stop1127-4"/> + <stop style="stop-color:#e6e6e6;stop-opacity:0;" offset="1" id="stop1129-5"/> + </linearGradient> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient961-9" id="radialGradient967-9" cx="172.61411" cy="303.20566" fx="172.61411" fy="303.20566" r="22.630014" gradientTransform="matrix(1,0,0,0.63328545,0,119.49923)" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" id="linearGradient961-9"> + <stop style="stop-color:#999999;stop-opacity:1;" offset="0" id="stop963-8"/> + <stop style="stop-color:#999999;stop-opacity:0;" offset="1" id="stop965-3"/> + </linearGradient> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient1125-6" id="radialGradient1131-8" cx="335.08649" cy="219.03677" fx="335.08649" fy="219.03677" r="29.875" gradientTransform="matrix(0.54659184,-0.27740671,0.6404924,1.2620022,11.607646,18.444794)" gradientUnits="userSpaceOnUse"/> + <linearGradient id="linearGradient1125-6"> + <stop style="stop-color:#969696;stop-opacity:1;" offset="0" id="stop1127-9"/> + <stop style="stop-color:#e6e6e6;stop-opacity:0;" offset="1" id="stop1129-8"/> + </linearGradient> + <radialGradient r="38.624973" fy="25.979427" fx="250.46019" cy="25.979427" cx="250.46019" gradientTransform="matrix(-1.1864466,0.79500993,0.21180507,0.31609089,435.38812,-174.97097)" gradientUnits="userSpaceOnUse" id="radialGradient1193-8" xlink:href="#linearGradient1117-8-2" inkscape:collect="always"/> + <linearGradient id="linearGradient1117-8-2"> + <stop style="stop-color:#afafaf;stop-opacity:1;" offset="0" id="stop1119-1-6"/> + <stop style="stop-color:#e6e6e6;stop-opacity:0;" offset="1" id="stop1121-2-2"/> + </linearGradient> + <linearGradient id="linearGradient1284-7"> + <stop style="stop-color:#bebebe;stop-opacity:1;" offset="0" id="stop1286-8"/> + <stop style="stop-color:#b3b3b3;stop-opacity:0;" offset="1" id="stop1288-0"/> + </linearGradient> + <radialGradient r="103.51558" fy="230.12292" fx="458.02847" cy="230.12292" cx="458.02847" gradientTransform="matrix(0.41734111,-0.01064379,0.00887794,0.34810258,9.439031,55.321448)" gradientUnits="userSpaceOnUse" id="radialGradient1847" xlink:href="#linearGradient1284-7" inkscape:collect="always"/> + <linearGradient id="linearGradient1117-8-2-0"> + <stop style="stop-color:#afafaf;stop-opacity:1;" offset="0" id="stop1119-1-6-8"/> + <stop style="stop-color:#e6e6e6;stop-opacity:0;" offset="1" id="stop1121-2-2-9"/> + </linearGradient> + <radialGradient r="38.624973" fy="25.979427" fx="250.46019" cy="25.979427" cx="250.46019" gradientTransform="matrix(1.1864466,0.79500993,-0.21180507,0.31609089,-32.887133,-175.8174)" gradientUnits="userSpaceOnUse" id="radialGradient2262" xlink:href="#linearGradient1117-8-2-0" inkscape:collect="always"/> + <linearGradient id="linearGradient1125-6-2"> + <stop style="stop-color:#969696;stop-opacity:1;" offset="0" id="stop1127-9-0"/> + <stop style="stop-color:#e6e6e6;stop-opacity:0;" offset="1" id="stop1129-8-5"/> + </linearGradient> + <radialGradient r="29.875" fy="219.03677" fx="335.08649" cy="219.03677" cx="335.08649" gradientTransform="matrix(-0.54659184,-0.27740671,-0.6404924,1.2620022,394.97125,17.340932)" gradientUnits="userSpaceOnUse" id="radialGradient2300" xlink:href="#linearGradient1125-6-2" inkscape:collect="always"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient3972" id="radialGradient3978" cx="9.0" cy="10.0" fx="1.0" fy="10.0" r="10.0" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient3972" id="radialGradient3980" cx="212.03125" cy="217.67747" fx="212.03125" fy="217.67747" r="16.494078" gradientTransform="matrix(1,0,0,1.5166132,0,-112.45505)" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient3972" id="radialGradient3982" cx="248.85938" cy="217.67747" fx="248.85938" fy="217.67747" r="16.697203" gradientTransform="matrix(1,0,0,1.4981632,0,-108.43892)" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient4117" id="radialGradient4123" cx="206.64375" cy="214.43469" fx="206.64375" fy="214.43469" r="190.25014" gradientTransform="matrix(0.97267227,0.01617535,-0.01665626,0.97473856,9.2187856,2.0743911)" gradientUnits="userSpaceOnUse"/> + </defs> + <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.8075" inkscape:cx="200.0" inkscape:cy="200.0" inkscape:document-units="px" inkscape:current-layer="layer3" showgrid="false" inkscape:snap-page="false" inkscape:snap-global="false" inkscape:window-width="1920" inkscape:window-height="996" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:snap-object-midpoints="true" inkscape:snap-nodes="true" inkscape:snap-grids="false" inkscape:snap-to-guides="false" inkscape:snap-center="true" inkscape:snap-bbox="true" inkscape:bbox-nodes="true" inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-midpoints="true" inkscape:bbox-paths="true"/> + <metadata id="metadata7"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title>Mumble logo</dc:title> + <dc:date>2009.08.17</dc:date> + <dc:creator> + <cc:Agent> + <dc:title>Martin Skilnand</dc:title> + </cc:Agent> + </dc:creator> + <dc:rights> + <cc:Agent> + <dc:title>Martin Skilnand</dc:title> + </cc:Agent> + </dc:rights> + <dc:publisher> + <cc:Agent> + <dc:title>Mumble team</dc:title> + </cc:Agent> + </dc:publisher> + <dc:identifier>mumble.svg</dc:identifier> + <dc:source>https://github.com/mumble-voip/mumble/</dc:source> + <dc:description>Logo for voice chat program mumble</dc:description> + <cc:license rdf:resource="BSD"/> + </cc:Work> + </rdf:RDF> + </metadata> + <g inkscape:label="Circle" inkscape:groupmode="layer" id="layer1" transform="translate(0,-652.36218)" style="display:inline" sodipodi:insensitive="true"> + <path sodipodi:type="arc" style="fill:#1a1a1a;stroke:#000000;stroke-width:4.57597017;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" id="path26" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="M 385.62498,214.43469 A 178.98123,174.04742 0 0 1 206.64375,388.48212 178.98123,174.04742 0 0 1 27.662521,214.43469 178.98123,174.04742 0 0 1 206.64375,40.387268 178.98123,174.04742 0 0 1 385.62498,214.43469 Z" transform="matrix(1.0811038,0,0,1.1043488,-22.437604,617.97608)"/> + <path sodipodi:type="arc" style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" id="path26-9-9-8-6" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="M 385.62498,214.43469 A 178.98123,174.04742 0 0 1 206.64375,388.48212 178.98123,174.04742 0 0 1 27.662521,214.43469 178.98123,174.04742 0 0 1 206.64375,40.387268 178.98123,174.04742 0 0 1 385.62498,214.43469 Z" transform="matrix(1.070643,0,0,1.1009928,-22.08154,583.61968)"/> + <path sodipodi:type="arc" style="opacity:0.9;fill:#ffffff;stroke:none;display:inline" id="path26-9-0" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="M 385.62498,214.43469 A 178.98123,174.04742 0 0 1 206.64375,388.48212 178.98123,174.04742 0 0 1 27.662521,214.43469 178.98123,174.04742 0 0 1 206.64375,40.387268 178.98123,174.04742 0 0 1 385.62498,214.43469 Z" transform="matrix(1.0422741,0,0,1.0695007,-13.735541,622.74462)"/> + <path sodipodi:type="arc" style="fill:#ffffff;stroke:#333333;stroke-width:1.41267002;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" id="path26-9" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="M 385.62498,214.43469 A 178.98123,174.04742 0 0 1 206.64375,388.48212 178.98123,174.04742 0 0 1 27.662521,214.43469 178.98123,174.04742 0 0 1 206.64375,40.387268 178.98123,174.04742 0 0 1 385.62498,214.43469 Z" transform="matrix(1.0641261,0,0,1.0786838,-20.794262,620.64438)"/> + <path sodipodi:type="arc" style="fill:none;stroke:#000000;stroke-width:1.83038807;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" id="path26-8" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="M 385.62498,214.43469 A 178.98123,174.04742 0 0 1 206.64375,388.48212 178.98123,174.04742 0 0 1 27.662521,214.43469 178.98123,174.04742 0 0 1 206.64375,40.387268 178.98123,174.04742 0 0 1 385.62498,214.43469 Z" transform="matrix(1.0856629,0,0,1.109006,-24.345467,616.20735)"/> + </g> + <g inkscape:groupmode="layer" id="layer6" inkscape:label="Effects" style="display:inline" sodipodi:insensitive="true"> + <path sodipodi:type="arc" style="opacity:0.75;fill:url(#radialGradient4123);fill-opacity:1;stroke:none;display:inline" id="path26-9-5" sodipodi:cx="206.64375" sodipodi:cy="214.43469" sodipodi:rx="178.98123" sodipodi:ry="174.04742" d="m 385.62498,214.43469 a 178.98123,174.04742 0 1 1 -357.962459,0 178.98123,174.04742 0 1 1 357.962459,0 z" transform="matrix(1.0764906,0,0,1.1009349,-20.513668,-34.695518)"/> + </g> + <g inkscape:groupmode="layer" id="layer4" inkscape:label="Headstrap" style="display:inline" sodipodi:insensitive="true"> + <path style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff" d="m 152.40625,31.610002 c -24.65159,-0.615413 -49.62289,15.704618 -55.852503,40.126444 -1.451111,5.920437 -2.042948,11.533344 -2.147497,17.25104 0,21.207504 0,42.415014 0,63.622514 8.33333,0 16.66667,0 25,0 0.0881,-22.3821 -0.12668,-44.64411 0.1701,-67.071988 0.76858,-14.243077 11.77335,-29.258147 27.0486,-29.08431 0.11203,22.668722 -0.22918,45.351398 0.18004,68.010988 1.30284,18.42605 18.76217,33.67641 37.24339,32.11401 11.54558,-0.2802 23.17762,0.67313 34.64753,-0.72475 17.46577,-3.27442 29.55308,-21.06252 27.92904,-38.4493 0,-20.285732 0,-40.571465 0,-60.857198 15.88808,-1.160259 27.93757,14.263321 28.64235,29.08431 0.29501,22.427208 0.0825,44.692338 0.1701,67.071988 8.33333,0 16.66667,0 25,0 0,-22.5 0,-45 0,-67.499998 -0.81797,-7.276075 -1.9718,-16.180186 -5.9149,-23.198476 -10.22889,-20.751216 -34.15317,-31.947919 -56.71743,-30.261229 -6.591,-0.83713 -13.68143,3.619737 -15.48689,9.866559 0.10876,26.738504 0.18577,53.486212 -0.015,80.219854 -0.75343,11.19988 -11.79041,19.76398 -22.80523,18.34204 -7.79212,0.33854 -16.59364,0.0136 -21.90827,-6.68171 -7.16232,-7.57045 -4.76318,-18.40537 -5.18362,-27.81167 0.0193,-21.718966 -0.0713,-43.418377 0.1249,-65.100368 -3.25934,-6.591257 -10.50309,-9.993605 -17.67905,-8.911927 l -1.18772,-0.01641 -1.25823,-0.04042 2.5e-4,0 z" id="rect1019" transform="matrix(1.05,0,0,1.05,-5.3555131,0.50955272)"/> + <path style="opacity:0.96660007;fill:url(#radialGradient1131-6);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 107.26989,156.26167 0,177.84375 c -35.128105,-3.85349 -62.737498,-42.18816 -62.737498,-88.92187 0,-46.73372 27.609393,-85.06839 62.737498,-88.92188 z" id="path833-1-4"/> + </g> + <g inkscape:groupmode="layer" id="layer2" inkscape:label="Headphones" style="display:inline" sodipodi:insensitive="true"> + <path style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff" d="m 290.42422,313.15625 c -0.69916,-0.007 -3.31052,-0.57507 -3.94043,-0.16697 0,0 -1.03559,3.01675 -4.60424,5.67254 -3.13272,2.33137 -6.10765,4.56617 -9.29463,6.66254 -2.86157,1.88231 -5.93275,3.91773 -8.80984,5.30245 -2.26396,1.08961 -4.11397,1.24819 -4.11397,1.24819 l -32.21955,0 c -2.01273,0 -3.66178,1.58716 -3.66178,3.5625 l 0,0.875 c 0,1.97534 1.64905,3.59375 3.66178,3.59375 l 33.87945,0 c 0.77968,0 3.59712,-0.82022 5.27249,-1.55528 4.17684,-1.83257 6.89898,-4.16602 11.7099,-7.02744 5.11436,-3.27118 14.57263,-10.88603 14.57263,-10.88603 1.67973,-1.08826 2.12779,-3.28897 1.01893,-4.9375 l -0.47763,-0.75 c -0.69304,-1.03033 -1.82785,-1.58241 -2.99311,-1.59375 z" id="rect134" sodipodi:nodetypes="ccsasccccccaccccc" transform="matrix(1.05,0,0,1.05,-5.3555131,0.50955272)"/> + <path style="opacity:0.96660007;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff" d="m 288.25,148.4375 0,169.375 C 321.70534,314.14251 348,277.6333 348,233.125 c 0,-44.5083 -26.29466,-81.01751 -59.75,-84.6875 z" id="path833" transform="matrix(1.05,0,0,1.05,-5.3555131,0.50955272)"/> + <path style="opacity:0.96660007;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;display:inline" d="m 106.22355,149.3374 0,169.375 c -33.455343,-3.66999 -59.750003,-40.1792 -59.750003,-84.6875 0,-44.5083 26.29466,-81.01751 59.750003,-84.6875 z" id="path833-2" transform="matrix(1.05,0,0,1.05,-5.3555131,0.50955272)"/> + <path sodipodi:type="arc" style="opacity:0.96660007;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff" id="path906" sodipodi:cx="172.61411" sodipodi:cy="325.86444" sodipodi:rx="22.130014" sodipodi:ry="13.831259" d="m 194.74412,325.86444 a 22.130014,13.831259 0 1 1 -44.26003,0 22.130014,13.831259 0 1 1 44.26003,0 z" transform="matrix(1.304789,0,0,1.21464,-20.460693,-43.799678)"/> + <rect style="opacity:0.96660007;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.05377054;display:inline" id="rect908-1" width="13.329355" height="171.94623" x="274.71799" y="146.09026" rx="3.8877287" ry="3.5400696" transform="matrix(1.0433338,0,0,1.0500168,-4.6562937,0.09487302)"/> + <rect style="opacity:0.96660007;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.04323161;display:inline" id="rect908-1-6" width="13.063269" height="171.95677" x="106.56075" y="147.08498" rx="3.8101201" ry="3.5402865" transform="matrix(1.0433338,0,0,1.0500168,-3.8347589,0.09487302)"/> + </g> + <g inkscape:groupmode="layer" id="layer3" inkscape:label="Sign" style="display:inline" sodipodi:insensitive="true"> + <rect style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" id="rect287" width="140.83455" height="111.88522" x="131.63644" y="188.83058"/> + <path id="path1297-8" style="fill:url(#radialGradient3978);fill-rule:evenodd;fill-opacity:1;stroke:none" d="M 4.4,18.6 h -4.4 v -18.6 h 4.5 c 5.6 0.0 4.3 8 2 8.5 c 3.5 0.0 4.0 9.4 -1 10.1 z M 2.8,7.4 v -3.9 h 1.2 a 0.8 1.0 0 0 1 0 3.9 z M 2.8,15.2 v -4.6 h 1.7 a 0.8 1.0 0 0 1 0 4.6 z" transform="translate(144,198) scale(4.4, 5)"/> + <path id="path1297" style="fill:#ffffff;fill-rule:evenodd;fill-opacity:1;stroke:none" d="M 4.4,18.6 h -4.4 v -18.6 h 4.5 c 5.6 0.0 4.3 8 2 8.5 c 3.5 0.0 4.0 9.4 -1 10.1 z M 2.8,7.4 v -3.9 h 1.2 a 0.8 1.0 0 0 1 0 3.9 z M 2.8,15.2 v -4.6 h 1.7 a 0.8 1.0 0 0 1 0 4.6 z" transform="translate(140,198) scale(4.4, 5)" inkscape:connector-curvature="0"/> + <path id="path1299-8" style="font-size:64px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:url(#radialGradient3980);fill-opacity:1;stroke:none;display:inline;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="m 227.5625,240.9431 l -31.0625,0 l 0,-46.53125 l 11.6875,0 l 0,37.65625 l 19.375,0 z" transform="matrix(1.100722,0,0,2.0000717,-23.811797,-190.28066)"/> + <path style="fill:#ffffff;fill-opacity:1;stroke:none" d="m 187.3125,197.5625 l 0,94.53125 l 14.125,0 l 0.0625,0 l 21.375,0 l 0,-19.25 l -21.375,0 l 0,-75.28125 l -14.1875,0 z" id="rect3178"/> + <path id="path1301-2" style="font-size:64px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:url(#radialGradient3982);fill-opacity:1;stroke:none;display:inline;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="m 233.125,240.9431 l 0,-46.53125 l 31.46875,0 l 0,8.875 l -19.84375,0 l 0,8.15625 l 18.28125,0 l 0,8.875 l -18.28125,0 l 0,11.75 l 19.84375,0 l 0,8.875 z" transform="matrix(1.100722,0,0,2.0000717,-23.811797,-190.28066)"/> + <path style="fill:#ffffff;fill-opacity:1;stroke:none;display:inline" d="m 227.8125,197.5 l 0,94.53125 l 14.1875,0 l 21.375,0 l 0,-19.25 l -21.375,0 L 242,250.5 l 19.65625,0 l 0,-18.65625 l -19.65625,0 L 242,216.75 l 21.375,0 l 0,-19.25 l -21.375,0 l -0.0625,0 l -14.125,0 z" id="rect3178-7"/> + </g> + <g inkscape:groupmode="layer" id="layer5" inkscape:label="Shadow-Glows" style="display:inline" sodipodi:insensitive="true"> + <path style="fill:url(#radialGradient1847);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 155.36979,33.010124 c -25.88417,-0.646184 -52.10402,16.489853 -58.645119,42.132764 -1.523665,6.216465 -2.145097,12.11002 -2.254875,18.113595 0,22.267867 0,44.535757 0,66.803627 8.750004,0 17.499994,0 26.249994,0 0.0925,-23.5012 -0.13301,-46.87631 0.17861,-70.425571 0.807,-14.955237 12.36201,-30.72106 28.40103,-30.538528 0.11763,23.802159 -0.24064,47.618949 0.18905,71.411529 1.36798,19.34735 19.70027,35.36023 39.10555,33.71971 12.12286,-0.29421 24.3365,0.70678 36.37991,-0.76099 18.33906,-3.43814 31.03074,-22.11565 29.32549,-40.37177 0,-21.30001 0,-42.600022 0,-63.900042 16.68248,-1.218273 29.33444,14.976486 30.07447,30.538529 0.30976,23.548553 0.0866,46.926943 0.17861,70.425573 8.74998,0 17.5,0 26.25,0 0,-23.625 0,-47.25 0,-70.874984 -0.85887,-7.639884 -2.07039,-16.989202 -6.21065,-24.358407 -10.74033,-21.788774 -35.86083,-33.545313 -59.5533,-31.774288 -6.92055,-0.878987 -14.3655,3.800724 -16.26123,10.359887 0.1142,28.075433 0.19506,56.160521 -0.0157,84.230832 -0.7911,11.75988 -12.37993,20.75218 -23.94549,19.25915 -8.18173,0.35546 -17.42333,0.0143 -23.00369,-7.0158 -7.52043,-7.94897 -5.00134,-19.32564 -5.4428,-29.20225 0.0203,-22.804904 -0.0749,-45.589287 0.13115,-68.355379 -3.42231,-6.92082 -11.02825,-10.493285 -18.56301,-9.357523 l -1.2471,-0.01723 -1.32114,-0.04244 2.6e-4,0 z" id="rect1019-2"/> + <path style="fill:url(#radialGradient1193-8);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 154.53194,34.268657 c -31.65505,0 -56.16894,21.233495 -59.981238,48.759372 l 26.971868,0 c 3.64479,-12.426072 13.11379,-21.517343 24.51094,-22.574997 0.74035,-0.69976 1.77197,-1.148438 2.92031,-1.148438 l 26.61094,0 0.0984,-15.61875 c 0,0 -2.37838,-3.725289 -4.29844,-5.479687 -2.17544,-1.987733 -5.11175,-3.428347 -8.00625,-3.740625 -2.4252,-0.261648 -5.19957,-0.04115 -8.82656,-0.196875 z" id="rect1019-7-4-1"/> + <path sodipodi:type="arc" style="opacity:0.96660007;fill:url(#radialGradient967-9);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" id="path906-4" sodipodi:cx="172.61411" sodipodi:cy="325.86444" sodipodi:rx="22.130014" sodipodi:ry="13.831259" d="m 194.74412,325.86444 a 22.130014,13.831259 0 1 1 -44.26003,0 22.130014,13.831259 0 1 1 44.26003,0 z" transform="matrix(1.304789,0,0,1.21464,-20.43351,-43.907478)"/> + <path style="opacity:0.96660007;fill:url(#radialGradient1131-8);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 298.65695,157.25586 0,177.84375 c 35.12811,-3.85349 62.7375,-42.18816 62.7375,-88.92188 0,-46.73371 -27.60939,-85.06838 -62.7375,-88.92187 z" id="path833-1"/> + <path style="fill:url(#radialGradient2262);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 247.96904,33.42223 c 31.65505,0 56.16894,21.233495 59.98124,48.759372 l -26.97187,0 C 277.33362,69.75553 267.86462,60.664259 256.46748,59.606605 c -0.74036,-0.69976 -1.77197,-1.148438 -2.92032,-1.148438 l -26.61093,0 -0.0984,-15.61875 c 0,0 2.37838,-3.725289 4.29844,-5.479687 2.17544,-1.987733 5.11176,-3.428347 8.00625,-3.740625 2.4252,-0.261648 5.19957,-0.04115 8.82656,-0.196875 z" id="rect1019-7-4-1-2"/> + <path style="opacity:0.96660007;fill:url(#radialGradient2300);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="m 107.92195,156.152 0,177.84375 c -35.128104,-3.85349 -62.737497,-42.18816 -62.737497,-88.92187 0,-46.73372 27.609393,-85.06839 62.737497,-88.92188 z" id="path833-1-5"/> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/mumble/mumble-1.png b/static/pix/mumble/mumble-1.png Binary files differnew file mode 100644 index 0000000..8679301 --- /dev/null +++ b/static/pix/mumble/mumble-1.png diff --git a/static/pix/mumble/mumble-2.png b/static/pix/mumble/mumble-2.png Binary files differnew file mode 100644 index 0000000..a3fb8ae --- /dev/null +++ b/static/pix/mumble/mumble-2.png diff --git a/static/pix/networking-ethernet-ip-up.png b/static/pix/networking-ethernet-ip-up.png Binary files differnew file mode 100644 index 0000000..e6e2224 --- /dev/null +++ b/static/pix/networking-ethernet-ip-up.png diff --git a/static/pix/networking-ethernet-ip.png b/static/pix/networking-ethernet-ip.png Binary files differnew file mode 100644 index 0000000..ec1024c --- /dev/null +++ b/static/pix/networking-ethernet-ip.png diff --git a/static/pix/networking-ethernet-route.png b/static/pix/networking-ethernet-route.png Binary files differnew file mode 100644 index 0000000..61befb9 --- /dev/null +++ b/static/pix/networking-ethernet-route.png diff --git a/static/pix/networking-ethernet-unconfigured.png b/static/pix/networking-ethernet-unconfigured.png Binary files differnew file mode 100644 index 0000000..96f1dbd --- /dev/null +++ b/static/pix/networking-ethernet-unconfigured.png diff --git a/static/pix/networking-interfaces.png b/static/pix/networking-interfaces.png Binary files differnew file mode 100644 index 0000000..bbf0ee3 --- /dev/null +++ b/static/pix/networking-interfaces.png diff --git a/static/pix/networking-server-interfaces.png b/static/pix/networking-server-interfaces.png Binary files differnew file mode 100644 index 0000000..ddae269 --- /dev/null +++ b/static/pix/networking-server-interfaces.png diff --git a/static/pix/networking-server-routes.png b/static/pix/networking-server-routes.png Binary files differnew file mode 100644 index 0000000..f756a07 --- /dev/null +++ b/static/pix/networking-server-routes.png diff --git a/static/pix/networking-wlan0.png b/static/pix/networking-wlan0.png Binary files differnew file mode 100644 index 0000000..44f10a5 --- /dev/null +++ b/static/pix/networking-wlan0.png diff --git a/static/pix/nextcloud.svg b/static/pix/nextcloud.svg new file mode 100644 index 0000000..6f2e1a3 --- /dev/null +++ b/static/pix/nextcloud.svg @@ -0,0 +1 @@ +<svg height="64" viewBox="0 0 64.000005 64.000001" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m32.028095 17.446884c-6.630378 0-12.249342 4.49517-13.99122 10.563651-1.517121-3.258998-4.77612-5.506585-8.597016-5.506585-5.169446 0-9.439859 4.270413-9.439859 9.496049 0 5.225637 4.270413 9.49605 9.496049 9.49605 3.764706 0 7.079895-2.247586 8.597015-5.506585 1.685689 6.068481 7.304653 10.563652 13.935031 10.563652 6.574188 0 12.193152-4.438981 13.99122-10.451272 1.517121 3.146619 4.77612 5.338015 8.484636 5.338015 5.225637 0 9.496049-4.270412 9.496049-9.496049s-4.270412-9.43986-9.496049-9.43986c-3.708516 0-6.967515 2.191396-8.484636 5.338016-1.798068-5.956101-7.360843-10.395082-13.99122-10.395082zm0 5.562773c5.000878 0 8.990343 3.989465 8.990343 8.990342 0 5.000879-3.989465 8.990343-8.990343 8.990343s-8.990343-3.989464-8.990343-8.990343c0-5.000875 3.989465-8.99034 8.990343-8.990342zm-22.532046 5.057067c2.191397 0 3.933275 1.74188 3.933275 3.933275 0 2.191396-1.741878 3.933276-3.933275 3.933276-2.191396 0-3.933275-1.74188-3.933275-3.933276 0-2.191395 1.741879-3.933275 3.933275-3.933275zm45.007902 0c2.191396 0 3.933275 1.74188 3.933275 3.933275 0 2.191396-1.741879 3.933276-3.933275 3.933276s-3.933275-1.74188-3.933275-3.933276c.05619-2.191395 1.741879-3.933275 3.933275-3.933275z" fill="#0082c9" stroke-width=".561896"/></svg>
\ No newline at end of file diff --git a/static/pix/nginx-password.png b/static/pix/nginx-password.png Binary files differnew file mode 100644 index 0000000..a1ae5e5 --- /dev/null +++ b/static/pix/nginx-password.png diff --git a/static/pix/nginx-website.png b/static/pix/nginx-website.png Binary files differnew file mode 100644 index 0000000..40d5236 --- /dev/null +++ b/static/pix/nginx-website.png diff --git a/static/pix/openalias-01.png b/static/pix/openalias-01.png Binary files differnew file mode 100644 index 0000000..b239634 --- /dev/null +++ b/static/pix/openalias-01.png diff --git a/static/pix/openalias-02.png b/static/pix/openalias-02.png Binary files differnew file mode 100644 index 0000000..03a45b0 --- /dev/null +++ b/static/pix/openalias-02.png diff --git a/static/pix/openalias-03.png b/static/pix/openalias-03.png Binary files differnew file mode 100644 index 0000000..9e2ba0b --- /dev/null +++ b/static/pix/openalias-03.png diff --git a/static/pix/openalias-04.png b/static/pix/openalias-04.png Binary files differnew file mode 100644 index 0000000..35caf10 --- /dev/null +++ b/static/pix/openalias-04.png diff --git a/static/pix/openalias-05.png b/static/pix/openalias-05.png Binary files differnew file mode 100644 index 0000000..a435462 --- /dev/null +++ b/static/pix/openalias-05.png diff --git a/static/pix/peertube-login.webp b/static/pix/peertube-login.webp Binary files differnew file mode 100644 index 0000000..e8986a9 --- /dev/null +++ b/static/pix/peertube-login.webp diff --git a/static/pix/peertube.svg b/static/pix/peertube.svg new file mode 100644 index 0000000..38992a5 --- /dev/null +++ b/static/pix/peertube.svg @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + viewBox="2799 -911 16 22" + version="1.1" + id="svg13" + sodipodi:docname="logo.svg" + width="16" + height="22" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1916" + inkscape:window-height="1040" + id="namedview15" + showgrid="false" + inkscape:zoom="29.790476" + inkscape:cx="-1.1827326" + inkscape:cy="12.088" + inkscape:window-x="0" + inkscape:window-y="18" + inkscape:window-maximized="0" + inkscape:current-layer="svg13" /> + <defs + id="defs4"> + <style + id="style2"> + .cls-3 { + fill: #211f20; + } + + .cls-4 { + fill: #737373; + } + + .cls-5 { + fill: #f1680d; + } + + .cls-6 { + fill: rgba(255, 255, 255, 0); + } + </style> + </defs> + <g + id="Artboard_1" + data-name="Artboard – 1" + class="cls-1" + transform="translate(0.03356777,-1.9929667)"> + <g + id="Symbol_3_1" + data-name="Symbol 3 – 1" + transform="translate(2759,-975)"> + <g + id="Group_44" + data-name="Group 44" + transform="translate(0,2.333)"> + <path + id="Path_4" + data-name="Path 4" + class="cls-3" + d="m -949,-500 v 10.667 l 8,-5.333" + transform="translate(989,564)" + inkscape:connector-curvature="0" + style="fill:#211f20" /> + <path + id="Path_5" + data-name="Path 5" + class="cls-4" + d="m -949,-500 v 10.667 l 8,-5.333" + transform="translate(989,574.667)" + inkscape:connector-curvature="0" + style="fill:#737373" /> + <path + id="Path_6" + data-name="Path 6" + class="cls-5" + d="m -949,-500 v 10.667 l 8,-5.333" + transform="translate(997,569.333)" + inkscape:connector-curvature="0" + style="fill:#f1680d" /> + <path + id="Path_7" + data-name="Path 7" + class="cls-6" + d="M 0,0 V 10.667 L 8,5.333 Z" + transform="rotate(180,24,40)" + inkscape:connector-curvature="0" + style="fill:rgba(255,255,255,0)" /> + </g> + </g> + </g> +</svg> diff --git a/static/pix/pleroma.svg b/static/pix/pleroma.svg new file mode 100644 index 0000000..c92da7c --- /dev/null +++ b/static/pix/pleroma.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="128" height="128" version="1.1" viewBox="0 0 33.866 33.866" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.1014 0 0 .1014 -9.0749 -9.0242)"><g fill="#fba457" stroke-width="0"><path transform="matrix(2.6094 0 0 2.6094 89.5 89)" d="m33.916 0a9.9641 9.9641 0 0 0-9.9648 9.9648v118.04h31.809v-128h-21.844z"/><path transform="matrix(2.6094 0 0 2.6094 89.5 89)" d="m71.855 0v64h22.229a9.9641 9.9641 0 0 0 9.9648-9.9648v-54.035h-32.193z"/><path transform="matrix(2.6094 0 0 2.6094 89.5 89)" d="m71.855 96.191v31.809h22.229a9.9641 9.9641 0 0 0 9.9648-9.9648v-21.844h-32.193z"/></g></g></svg> diff --git a/static/pix/prosody.svg b/static/pix/prosody.svg new file mode 100644 index 0000000..9edae9b --- /dev/null +++ b/static/pix/prosody.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="64" viewBox="0 0 480 480" width="64"> + <g> + <title>Prosody Logo</title> + <rect fill="#6197df" height="220" id="svg_1" rx="60" ry="60" width="220" x="10" y="10"/> + <rect fill="#f29b00" height="220" id="svg_2" rx="60" ry="60" width="220" x="10" y="240"/> + <rect fill="#f29b00" height="220" id="svg_3" rx="60" ry="60" width="220" x="240" y="10"/> + <rect fill="#6197df" height="220" id="svg_4" rx="60" ry="60" width="220" x="240" y="240"/> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/radicale.svg b/static/pix/radicale.svg new file mode 100644 index 0000000..546d3d1 --- /dev/null +++ b/static/pix/radicale.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="200" height="300" xmlns="http://www.w3.org/2000/svg"> + <path fill="#a40000" d="M 186,188 C 184,98 34,105 47,192 C 59,279 130,296 130,296 C 130,296 189,277 186,188 z" /> + <path fill="#ffffff" d="M 73,238 C 119,242 140,241 177,222 C 172,270 131,288 131,288 C 131,288 88,276 74,238 z" /> + <g fill="none" stroke="#4e9a06" stroke-width="15"> + <path d="M 103,137 C 77,69 13,62 13,62" /> + <path d="M 105,136 C 105,86 37,20 37,20" /> + <path d="M 105,135 C 112,73 83,17 83,17" /> + </g> +</svg> diff --git a/static/pix/rainloop-1.png b/static/pix/rainloop-1.png Binary files differnew file mode 100644 index 0000000..55bf5b8 --- /dev/null +++ b/static/pix/rainloop-1.png diff --git a/static/pix/rainloop-2.png b/static/pix/rainloop-2.png Binary files differnew file mode 100644 index 0000000..5f237de --- /dev/null +++ b/static/pix/rainloop-2.png diff --git a/static/pix/rainloop.png b/static/pix/rainloop.png Binary files differnew file mode 100644 index 0000000..93500ab --- /dev/null +++ b/static/pix/rainloop.png diff --git a/static/pix/rdns-01.png b/static/pix/rdns-01.png Binary files differnew file mode 100644 index 0000000..464bb07 --- /dev/null +++ b/static/pix/rdns-01.png diff --git a/static/pix/rdns-02.png b/static/pix/rdns-02.png Binary files differnew file mode 100644 index 0000000..35eefec --- /dev/null +++ b/static/pix/rdns-02.png diff --git a/static/pix/rss-01.png b/static/pix/rss-01.png Binary files differnew file mode 100644 index 0000000..aa3c965 --- /dev/null +++ b/static/pix/rss-01.png diff --git a/static/pix/rss-02.png b/static/pix/rss-02.png Binary files differnew file mode 100644 index 0000000..e296352 --- /dev/null +++ b/static/pix/rss-02.png diff --git a/static/pix/rss-webui.png b/static/pix/rss-webui.png Binary files differnew file mode 100644 index 0000000..0d529b7 --- /dev/null +++ b/static/pix/rss-webui.png diff --git a/static/pix/rss.svg b/static/pix/rss.svg new file mode 100644 index 0000000..35afbe2 --- /dev/null +++ b/static/pix/rss.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="svg2" sodipodi:version="0.32" inkscape:version="0.47 r22583" inkscape:output_extension="org.inkscape.output.svg.inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" sodipodi:docname="rss-feed.svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> +<path fill="#E15A00" d="M9.496,210.008c0,19.6,15.888,35.486,35.486,35.486h164.034c19.604,0,35.487-15.889,37.487-34.82 l-0.001-164.013c-1.999-20.266-17.888-36.155-37.484-36.155H44.982c-19.599,0-35.486,15.889-35.486,35.487V210.008z"/> +<g id="layer1" transform="translate(-373.642,-318.344)" inkscape:groupmode="layer" inkscape:label="Layer 1"> + + <path id="path5270" sodipodi:cy="200.64285" sodipodi:type="arc" sodipodi:cx="360.35715" sodipodi:rx="24.642859" sodipodi:ry="23.928572" fill="#FFFFFF" d=" M469.09,505.078c0,11.498-9.598,20.817-21.438,20.817c-11.84,0-21.438-9.319-21.438-20.817c0-11.496,9.599-20.816,21.438-20.816 C459.491,484.262,469.09,493.582,469.09,505.078z"/> + <path id="path5805" sodipodi:nodetypes="ccccc" fill="#FFFFFF" d="M426.835,455.057l-0.073-30.273 c64.706,3.375,100.618,49.674,101.5,101.939h-30.318C497.441,480.781,466.204,456.728,426.835,455.057z"/> + <path id="path5807" sodipodi:nodetypes="ccccc" fill="#FFFFFF" d="M427.202,404.572l-0.879-30.758 c99.428,4.616,152.676,76.769,153.348,152.909l-31.197-0.439C549.839,477.58,513.808,406.017,427.202,404.572z"/> +</g> +<g> + + <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="102.5" y1="-491.002" x2="102.5" y2="-598.5135" gradientTransform="matrix(1 0 0 -1 25.5 -353)"> + <stop offset="0" style="stop-color:#000000;stop-opacity:0.15"/> + <stop offset="0.6626" style="stop-color:#000000;stop-opacity:0"/> + </linearGradient> + <path fill="url(#SVGID_1_)" d="M9.496,115.402v94.606c0,19.6,15.888,35.486,35.487,35.486h164.033 c19.604,0,35.488-15.889,37.488-34.82v-95.952c-36.779,15.182-77.074,23.577-119.337,23.577 C85.542,138.299,45.825,130.154,9.496,115.402z"/> +</g> +<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="102.4995" y1="-364.168" x2="102.4995" y2="-491.7969" gradientTransform="matrix(1 0 0 -1 25.5 -353)"> + <stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.85"/> + <stop offset="0.66" style="stop-color:#FFFFFF;stop-opacity:0"/> +</linearGradient> +<path fill="url(#SVGID_2_)" d="M209.018,10.505H44.983c-19.599,0-35.487,15.889-35.487,35.487v69.409 c36.33,14.751,76.046,22.897,117.671,22.897c42.263,0,82.558-8.396,119.336-23.577v-68.06 C244.504,26.395,228.615,10.505,209.018,10.505z"/> +<path fill="none" stroke="#E15A00" stroke-width="2" stroke-miterlimit="10" d="M246.503,114.721V46.66 c-1.999-20.266-17.888-36.155-37.485-36.155H44.982c-19.599,0-35.486,15.889-35.486,35.487v69.409"/> +<g> + <g> + <g> + <path fill="none" stroke="#B34700" stroke-width="2" stroke-miterlimit="10" d="M9.496,115.401v94.605 c0,19.6,15.888,35.486,35.486,35.486h164.034c19.604,0,35.487-15.889,37.487-34.819v-95.952"/> + </g> + </g> +</g> +</svg>
\ No newline at end of file diff --git a/static/pix/rsync.png b/static/pix/rsync.png Binary files differnew file mode 100644 index 0000000..7190b41 --- /dev/null +++ b/static/pix/rsync.png diff --git a/static/pix/searxng.svg b/static/pix/searxng.svg new file mode 100644 index 0000000..417e7ed --- /dev/null +++ b/static/pix/searxng.svg @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg8" version="1.1" viewBox="0 0 92 92" height="92mm" width="92mm"> + <defs id="defs2"/> + <metadata id="metadata5"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title/> + </cc:Work> + </rdf:RDF> + </metadata> + <g transform="translate(-40.921303,-17.416526)" id="layer1"> + <circle r="0" style="fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" cy="92" cx="75" id="path3713"/> + <circle r="30" cy="53.902557" cx="75.921303" id="path834" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> + <path d="m 67.514849,37.91524 a 18,18 0 0 1 21.051475,3.312407 18,18 0 0 1 3.137312,21.078282" id="path852" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> + <rect transform="rotate(-46.234709)" ry="1.8669105e-13" y="122.08995" x="3.7063529" height="39.963303" width="18.846331" id="rect912" style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/server-features.png b/static/pix/server-features.png Binary files differnew file mode 100644 index 0000000..6891b46 --- /dev/null +++ b/static/pix/server-features.png diff --git a/static/pix/server-location.png b/static/pix/server-location.png Binary files differnew file mode 100644 index 0000000..b97e8d2 --- /dev/null +++ b/static/pix/server-location.png diff --git a/static/pix/server-size.png b/static/pix/server-size.png Binary files differnew file mode 100644 index 0000000..39ddc33 --- /dev/null +++ b/static/pix/server-size.png diff --git a/static/pix/server-type.png b/static/pix/server-type.png Binary files differnew file mode 100644 index 0000000..188b101 --- /dev/null +++ b/static/pix/server-type.png diff --git a/static/pix/smtp-01.png b/static/pix/smtp-01.png Binary files differnew file mode 100644 index 0000000..8b023d7 --- /dev/null +++ b/static/pix/smtp-01.png diff --git a/static/pix/smtp-02.png b/static/pix/smtp-02.png Binary files differnew file mode 100644 index 0000000..82f8774 --- /dev/null +++ b/static/pix/smtp-02.png diff --git a/static/pix/ssh-01.png b/static/pix/ssh-01.png Binary files differnew file mode 100644 index 0000000..855f313 --- /dev/null +++ b/static/pix/ssh-01.png diff --git a/static/pix/tor.svg b/static/pix/tor.svg new file mode 100644 index 0000000..4d7eefd --- /dev/null +++ b/static/pix/tor.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="66px" height="104px" viewBox="0 0 66 104" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch --> + <title>onion-bg</title> + <desc>Created with Sketch.</desc> + <defs></defs> + <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="styleguide-portal" transform="translate(-2.000000, -23.000000)" fill-rule="nonzero"> + <g id="onion-bg" transform="translate(2.000000, 23.000000)"> + <g id="layer5_17_"> + <g id="path2554_28_" transform="translate(30.297143, 0.000000)" fill="#68B044"> + <path d="M8.13239105,7.75250545 L5.42159403,18.7352215 C9.24860159,10.982716 15.4674889,5.16833696 22.4836694,-7.10542736e-15 C17.3809926,6.13740015 12.5972332,12.1132898 9.72697753,18.2506899 C14.6701956,11.3057371 21.2080002,7.42948439 28.543098,5.00682643 C18.6566618,13.8899056 11.0026467,23.4190269 4.94321809,32.9481481 L0.159458648,30.8485113 C1.11621054,23.0960058 3.9864662,15.3435004 8.13239105,7.75250545 L8.13239105,7.75250545 Z" id="Shape"></path> + </g> + <g id="path2534_7_" transform="translate(0.000000, 28.227160)" fill="#F5F8DE"> + <path d="M25.832301,0.521713871 L34.7619853,4.23645606 C34.7619853,6.49760349 34.6025266,13.6040668 36.0376545,15.7037037 C51.0267674,35.2464779 48.475429,74.1705156 33.0079401,75.1395788 C9.56751888,75.1395788 0.478375944,58.9885258 0.478375944,44.129557 C0.478375944,30.5626725 16.5836994,21.5180828 26.1512183,13.6040668 C28.7025566,11.5044299 28.2241807,6.65911402 25.832301,0.521713871 L25.832301,0.521713871 Z" id="Shape"></path> + </g> + <g id="path2536_18_" transform="translate(34.819291, 32.302106)" fill="#623676"> + <path d="M0.102153196,0 L3.29132616,1.6151053 C2.97240886,3.71474219 3.4507848,8.5600581 5.52374723,9.85214234 C14.9318075,15.828032 23.8614918,22.2884532 27.369582,28.7488744 C39.8073566,51.5218591 18.5993564,72.6797386 0.261611844,70.5801017 C10.148048,63.1506173 13.1777623,47.8071169 9.35075478,31.0100218 C7.7561683,24.3880901 5.52374723,18.573711 1.21836373,11.7902687 C-0.376222748,8.72156863 0.261611844,4.68380537 0.102153196,0 L0.102153196,0 Z" id="Shape"></path> + </g> + </g> + <g id="layer4_17_" transform="translate(9.000000, 32.000000)" fill="#010101"> + <g id="path2540_18_" transform="translate(0.000000, 10.329661)"> + <path d="M22.9646678,0.502650405 C22.3354989,4.00722163 21.5490376,10.3791693 18.560485,12.609351 C17.302147,13.5651431 16.043809,14.3616366 14.6281788,15.3174288 C9.28024249,18.9812987 3.77501389,22.4858699 1.41563021,31.5658953 C0.943753473,33.4774796 1.41563021,35.5483626 1.7302147,37.4599469 C3.14584491,42.8761025 6.9208588,48.9294527 9.90941147,52.2747253 C9.90941147,52.434024 10.5385804,52.7526214 10.5385804,52.91192 C13.0552564,55.9385952 13.8417176,56.7350886 23.1219601,58.8059716 L22.9646678,59.9210625 C17.302147,58.3280756 12.7406719,57.053686 9.75211922,53.5491148 C9.75211922,53.5491148 9.28024249,52.91192 9.28024249,52.91192 C6.13439758,49.2480501 2.35938368,43.1946998 0.943753473,37.4599469 C0.471876737,35.2297652 -8.8817842e-14,33.4774796 0.629168982,31.0879993 C3.14584491,21.8486751 8.80836575,18.1848052 14.3135943,14.3616366 C15.5719323,13.5651431 17.1448548,12.7686497 18.2459005,11.8128575 C20.4479919,10.0605719 21.7063299,4.80371509 22.9646678,0.502650405 L22.9646678,0.502650405 Z" id="Shape"></path> + </g> + <g id="path2542_18_" transform="translate(6.291690, 25.222293)"> + <path d="M19.0323617,0.106199128 C19.0323617,4.08866643 18.7177772,6.00025073 19.6615307,8.86762718 C20.2906997,10.4606141 22.3354989,12.8500945 22.9646678,15.0802762 C23.7511291,18.1069513 24.6948825,21.2929252 24.5375903,23.3638081 C24.5375903,25.5939898 24.3802981,29.8950545 23.4365446,34.5147166 C22.6500834,38.3378852 20.9198687,41.523859 18.0886082,43.2761446 C15.1000556,42.6389499 11.6396262,41.6831577 9.59482698,39.7715734 C5.66252084,36.2670022 2.04479919,30.3729506 1.57292246,25.2753924 C1.25833796,21.1336265 5.03335186,14.9209775 10.3812882,11.8943023 C14.9427633,9.18622457 15.8865168,6.15954942 16.8302703,1.38058866 C15.4146401,5.68165334 14.1563021,9.18622457 9.90941147,11.4164063 C3.61772165,14.7616788 0.314584491,20.337133 0.629168982,25.7532885 C1.10104572,32.6031323 3.77501389,37.2227943 9.12295024,40.8866643 C11.3250417,42.4796512 15.5719323,44.2319368 18.2459005,44.5505342 L18.2459005,44.2319368 C20.2906997,43.9133394 22.8073756,40.5680669 24.0657136,36.1077035 C25.1667593,32.1252362 25.638636,26.8683794 25.4813438,23.6824055 C25.4813438,21.7708212 24.5375903,17.6290552 23.1219601,13.9651853 C22.3354989,11.8943023 21.0771609,9.82341933 20.1334074,8.38973111 C19.5042384,6.95604288 19.5042384,3.77006904 19.0323617,0.106199128 Z" id="Shape"></path> + </g> + <g id="path2544_18_" transform="translate(17.302147, 40.596412)"> + <path d="M7.39273554,0.343351713 C7.39273554,3.05142948 8.49378126,6.39670201 8.96565799,9.90127323 C9.28024249,12.4500523 9.12295024,15.1581301 9.12295024,17.3883117 C9.12295024,20.0963895 8.17919677,24.7160516 6.9208588,27.105532 C5.81981308,26.6276359 5.34793635,25.9904411 4.56147512,25.034649 C3.61772165,23.7602594 2.98855266,22.4858699 2.51667593,20.892883 C2.04479919,19.7777921 1.57292246,18.5034026 1.25833796,16.9104157 C0.943753473,14.680234 1.10104572,11.0163641 3.61772165,7.35249416 C5.50522859,4.4851177 5.97710533,4.16652032 6.76356656,0.980546481 C5.81981308,4.00722163 5.1906441,4.16652032 3.14584491,6.71529939 C0.786461228,9.42337715 0.471876737,13.4058444 0.471876737,16.751117 C0.471876737,18.1848052 0.943753473,19.6184934 1.57292246,21.0521817 C2.20209144,22.6451686 2.67396817,24.0788568 3.4604294,25.1939477 C4.71876737,27.105532 6.29168982,28.0613241 7.07815105,28.2206228 C7.07815105,28.2206228 7.07815105,28.2206228 7.07815105,28.2206228 C7.07815105,28.2206228 7.07815105,28.2206228 7.07815105,28.2206228 L7.07815105,28.0613241 C8.49378126,26.4683372 9.43753473,24.7160516 9.75211922,23.1230647 C10.0667037,21.2114804 10.223996,19.1405974 10.3812882,16.751117 C10.5385804,14.8395327 10.3812882,12.1314549 9.90941147,9.42337715 C9.12295024,6.23740331 7.86461228,2.73283209 7.39273554,0.343351713 L7.39273554,0.343351713 Z" id="Shape"></path> + </g> + <g id="path2550_18_" transform="translate(24.373837, 7.143687)"> + <path d="M0.792922455,0.343351713 C0.792922455,4.32581901 1.10750695,11.6535588 2.20855266,14.5209353 C2.52313716,15.4767274 5.35439758,19.7777921 7.24190452,25.034649 C8.65753473,28.6985189 8.81482698,32.0437914 9.12941147,32.9995836 C10.0731649,37.3006482 8.97211922,44.6283881 7.39919677,51.4782318 C6.61273554,55.1421017 4.09605961,59.7617638 1.10750695,61.6733481 L0.478337964,62.7884389 C2.05126042,62.7884389 6.1408588,58.646673 7.55648901,53.7084135 C9.9158727,45.2655828 10.8596262,41.2831155 9.75858045,31.8844927 C9.6012882,30.9287006 9.28670371,27.9020254 7.8710735,24.5567529 C5.82627431,19.4591947 2.83772165,14.680234 2.36584491,13.5651431 C1.89396817,11.9721562 0.950214701,5.12231247 0.792922455,0.343351713 L0.792922455,0.343351713 Z" id="Shape"></path> + </g> + <g id="path2552_18_" transform="translate(24.373837, 0.000000)"> + <path d="M2.20855266,0.477896076 C2.05126042,4.46036337 1.89396817,7.8056359 2.6804294,10.6730124 C3.46689063,14.0182849 7.71378126,18.637947 9.44399596,24.0541025 C12.7471331,34.4085175 11.9606719,47.9489063 9.44399596,58.4626199 C8.50024249,62.1264898 4.25335186,67.5426454 0.00646122758,69.294931 L3.15230614,70.0914244 C4.88252084,70.0914244 9.28670371,65.7903598 11.0169184,61.011399 C13.8481788,53.5243605 14.3200556,44.6036337 13.2190099,35.0457122 C13.2190099,34.0899201 11.6460874,25.9656868 10.2304572,22.6204143 C8.18565799,17.5228561 5.03981308,14.0182849 3.78147512,10.832311 C2.83772165,8.44283067 2.52313716,2.23018169 3.15230614,0.79649346 L2.20855266,0.477896076 Z" id="Shape"></path> + </g> + </g> + </g> + </g> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/transmission-web-interface.png b/static/pix/transmission-web-interface.png Binary files differnew file mode 100644 index 0000000..8b305dd --- /dev/null +++ b/static/pix/transmission-web-interface.png diff --git a/static/pix/transmission.png b/static/pix/transmission.png Binary files differnew file mode 100644 index 0000000..6514c24 --- /dev/null +++ b/static/pix/transmission.png diff --git a/static/pix/webrtc.svg b/static/pix/webrtc.svg new file mode 100644 index 0000000..582a506 --- /dev/null +++ b/static/pix/webrtc.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="256px" height="249px" viewBox="0 0 256 249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid"> + <g> + <path d="M142.076578,191.086817 C142.076578,159.280656 116.294759,133.494615 84.4885969,133.494615 C52.6782136,133.494615 26.896394,159.280656 26.896394,191.086817 C26.896394,222.892979 52.6782136,248.67902 84.4885969,248.67902 C116.294759,248.67902 142.076578,222.892979 142.076578,191.086817" fill="#FF6600" transform="translate(84.486486, 191.086817) scale(1, -1) translate(-84.486486, -191.086817) "></path> + <path d="M255.979703,110.454356 C255.979703,78.652416 230.197884,52.862153 198.391722,52.862153 C166.581339,52.862153 140.799519,78.652416 140.799519,110.454356 C140.799519,142.260518 166.581339,168.050781 198.391722,168.050781 C230.197884,168.050781 255.979703,142.260518 255.979703,110.454356" fill="#FFCC00" transform="translate(198.389611, 110.456467) scale(1, -1) translate(-198.389611, -110.456467) "></path> + <path d="M115.200498,109.176452 C115.200498,77.3745125 89.4186786,51.5842495 57.6082953,51.5842495 C25.8063553,51.5842495 0.0203140271,77.3745125 0.0203140271,109.176452 C0.0203140271,140.982614 25.8063553,166.772877 57.6082953,166.772877 C89.4186786,166.772877 115.200498,140.982614 115.200498,109.176452" fill="#0089CC" transform="translate(57.610406, 109.178563) scale(1, -1) translate(-57.610406, -109.178563) "></path> + <path d="M230.385749,191.086817 C230.385749,159.280656 204.603929,133.494615 172.789324,133.494615 C140.987384,133.494615 115.201343,159.280656 115.201343,191.086817 C115.201343,222.892979 140.987384,248.67902 172.789324,248.67902 C204.603929,248.67902 230.385749,222.892979 230.385749,191.086817" fill="#009939" transform="translate(172.793546, 191.086817) scale(1, -1) translate(-172.793546, -191.086817) "></path> + <path d="M185.592001,57.9843213 C185.592001,26.1781597 159.805959,0.392118349 127.999798,0.392118349 C96.1936359,0.392118349 70.4075946,26.1781597 70.4075946,57.9843213 C70.4075946,89.790483 96.1936359,115.576524 127.999798,115.576524 C159.805959,115.576524 185.592001,89.790483 185.592001,57.9843213" fill="#BF0000" transform="translate(127.999798, 57.984321) scale(1, -1) translate(-127.999798, -57.984321) "></path> + <path d="M140.798675,57.9788331 C140.798675,56.76721 140.904217,55.580917 140.980207,54.3861807 C166.525612,60.2796505 185.590734,83.1189569 185.590734,110.454356 C185.590734,111.665979 185.485192,112.856494 185.409202,114.05123 C159.863796,108.153539 140.798675,85.3142322 140.798675,57.9788331" fill="#FC0007" transform="translate(163.194704, 84.218705) scale(1, -1) translate(-163.194704, -84.218705) "></path> + <path d="M148.39686,162.570614 C158.322038,145.219495 176.973434,133.495881 198.394255,133.495881 C207.124696,133.495881 215.369643,135.496959 222.787141,138.975626 C212.866185,156.326744 194.214789,168.050358 172.789746,168.050358 C164.059305,168.050358 155.814358,166.049281 148.39686,162.570614" fill="#1CD306" transform="translate(185.592001, 150.773120) scale(1, -1) translate(-185.592001, -150.773120) "></path> + <path d="M115.200498,191.086817 C115.200498,177.015947 120.258075,164.139813 128.642338,154.138646 C137.018157,164.139813 142.075734,177.015947 142.075734,191.086817 C142.075734,205.157688 137.018157,218.033822 128.642338,228.034989 C120.258075,218.033822 115.200498,205.157688 115.200498,191.086817" fill="#0F7504" transform="translate(128.638116, 191.086817) scale(1, -1) translate(-128.638116, -191.086817) "></path> + <path d="M34.806984,138.212768 C41.8023132,135.190043 49.5026635,133.497148 57.6082953,133.497148 C78.818032,133.497148 97.2963396,144.992791 107.293286,162.061056 C100.297956,165.083782 92.5933844,166.772455 84.4919743,166.772455 C63.2822376,166.772455 44.7997083,155.276811 34.806984,138.212768" fill="#0C5E87" transform="translate(71.050135, 150.134801) scale(1, -1) translate(-71.050135, -150.134801) "></path> + <path d="M70.6545631,114.036032 C70.5194692,112.431792 70.4054838,110.819109 70.4054838,109.176875 C70.4054838,81.862584 89.4410536,59.044386 114.956907,53.1255861 C115.087779,54.7298257 115.201765,56.3425087 115.201765,57.9805218 C115.201765,85.2948125 96.1704167,108.121454 70.6545631,114.036032" fill="#6B0001" transform="translate(92.803624, 83.580809) scale(1, -1) translate(-92.803624, -83.580809) "></path> + <path d="M76.0304545,111.503866 L67.0213825,111.503866 C59.0677312,111.503866 52.6001125,117.950377 52.6001125,125.88292 L52.6001125,207.428953 C52.6001125,215.361496 59.0677312,221.812228 67.0213825,221.812228 L179.989405,221.812228 C187.943056,221.812228 194.406453,215.361496 194.406453,207.428953 L194.406453,125.88292 C194.406453,117.950377 187.943056,111.503866 179.989405,111.503866 L141.50454,111.503866 L64.2899534,73.6522544 L76.0304545,111.503866 L76.0304545,111.503866 Z" fill="#FFFFFF" transform="translate(123.503283, 147.732241) scale(1, -1) translate(-123.503283, -147.732241) "></path> + </g> +</svg>
\ No newline at end of file diff --git a/static/pix/wireguard.svg b/static/pix/wireguard.svg new file mode 100644 index 0000000..441d27e --- /dev/null +++ b/static/pix/wireguard.svg @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + version="1.1" + id="svg97" + width="92.160004" + height="95.360001" + viewBox="0 0 92.160004 95.360001" + sodipodi:docname="wireguard.svg" + inkscape:version="1.2 (dc2aedaf03, 2022-05-15)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs101" /> + <sodipodi:namedview + id="namedview99" + pagecolor="#505050" + bordercolor="#eeeeee" + borderopacity="1" + inkscape:showpageshadow="0" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#505050" + showgrid="false" + inkscape:zoom="5.6568543" + inkscape:cx="82.731493" + inkscape:cy="62.137008" + inkscape:window-width="1920" + inkscape:window-height="1024" + inkscape:window-x="0" + inkscape:window-y="28" + inkscape:window-maximized="1" + inkscape:current-layer="g103" /> + <g + inkscape:groupmode="layer" + inkscape:label="Image" + id="g103" + style="display:inline"> + <path + style="fill:#800000;stroke-width:0.321789" + d="M 37.466376,94.244866 C 25.400413,92.597528 16.545594,88.016978 10.171711,80.125489 6.1353724,75.128105 3.1892009,68.457061 1.5531875,60.610489 0.61615096,56.116316 0.38392054,46.243203 1.0990513,41.303201 2.3934427,32.361771 5.3273701,24.37919 9.7021439,17.896056 11.823796,14.751905 16.888449,9.6763519 19.792133,7.7843509 27.420521,2.8138008 34.93289,0.75789563 45.467117,0.75789563 c 21.998935,0 36.785489,9.24633437 43.377501,27.12483437 2.377256,6.447457 3.171201,11.418696 3.171201,19.856235 0,8.418355 -0.875209,13.934697 -3.227438,20.342139 -4.774958,13.00693 -14.2849,21.638832 -27.53824,24.995674 -6.278818,1.590316 -16.878246,2.110886 -23.783765,1.168088 z m 16.680832,-1.483059 c 4.375074,-1.467242 7.717071,-3.84276 10.272266,-7.301599 4.427637,-5.993471 4.956178,-14.37139 1.34483,-21.316978 -1.218688,-2.343859 -3.668485,-5.319714 -4.630748,-5.625123 -0.436924,-0.138669 -1.690015,0.441004 -4.097724,1.895602 -1.907579,1.152452 -4.180846,2.410547 -5.051704,2.795771 l -1.58338,0.700403 1.546552,0.587061 c 4.566849,1.733543 7.025098,5.600533 6.484462,10.2005 -0.407342,3.465822 -2.227825,6.197488 -5.150657,7.728637 -2.261157,1.184525 -6.078195,1.234298 -8.207654,0.107024 -1.671516,-0.88485 -3.30536,-2.537943 -4.466509,-4.519139 -1.144603,-1.952964 -1.196673,-5.814921 -0.111424,-8.264318 1.278992,-2.886668 2.756299,-3.97611 9.355437,-6.899183 6.382549,-2.82713 7.840535,-3.629499 9.836945,-5.413537 5.286242,-4.723911 8.269537,-11.375935 8.318004,-18.547142 0.02613,-3.865962 -0.5747,-6.094255 -2.363186,-8.764342 -1.609909,-2.403485 -2.498122,-3.237392 -7.724653,-7.252361 -3.74025,-2.873222 -5.792187,-4.888987 -5.792187,-5.690079 0,-0.116983 0.192387,-0.475803 0.427527,-0.797377 0.372779,-0.509806 1.087998,-0.605756 5.585007,-0.749246 3.665956,-0.116968 5.222885,-0.05874 5.383647,0.20139 0.376422,0.609061 1.228871,0.414204 2.181759,-0.498721 1.527884,-1.463802 1.245009,-1.709631 -1.967248,-1.709631 -2.98425,0 -4.008901,-0.18726 -3.706043,-0.677296 0.09792,-0.158437 2.278916,-0.288069 4.846657,-0.288069 h 4.668625 L 69.331091,11.940031 C 69.212996,11.541818 68.552761,10.640058 67.863893,9.9361177 66.627891,8.6730736 66.583704,8.6574738 64.506339,8.7507664 61.738867,8.8750437 60.414738,8.3990116 59.175416,6.8342404 57.936058,5.2694235 54.631669,3.5352446 51.233138,2.6660461 48.779112,2.0384126 42.261399,1.7653632 42.594382,2.3041387 c 0.08806,0.1425055 1.617063,0.6030293 3.397764,1.0233947 1.780701,0.420367 3.237638,0.8829938 3.237638,1.0280607 0,0.4542605 -3.255662,0.2641074 -6.274106,-0.36645 -1.592433,-0.3326616 -2.95506,-0.5451103 -3.028061,-0.4721094 -0.155343,0.1553445 5.917642,3.0330443 6.400816,3.0330443 0.672038,0 0.292837,0.6447409 -0.672937,1.1441606 -0.833093,0.4308105 -1.625698,0.4797646 -4.749277,0.2933333 -3.1516,-0.1881034 -3.954026,-0.1368711 -5.033546,0.3213806 L 34.588424,8.854111 36.37819,9.768277 c 2.253334,1.150945 2.533609,1.499063 2.762433,3.431132 l 0.18581,1.56886 -1.743436,0.722614 c -1.872293,0.77602 -4.097441,2.440368 -3.744514,2.800789 0.118491,0.121004 1.580129,0.336924 3.248099,0.479832 2.553812,0.218807 5.063864,0.933947 5.063864,1.442751 0,0.07291 -0.724024,0.526611 -1.608941,1.008242 -0.884917,0.481634 -1.60894,1.018388 -1.60894,1.192789 0,0.196118 0.914731,0.247912 2.397649,0.13576 l 2.397653,-0.181333 1.383358,1.188444 c 0.760848,0.653645 2.817805,2.329982 4.571017,3.725193 4.226927,3.363811 7.098041,6.367687 8.164602,8.542143 0.739961,1.508604 0.871903,2.191625 0.873177,4.520134 0.0013,2.446106 -0.111698,2.972944 -1.044463,4.867648 -1.305996,2.652859 -4.430452,5.872449 -7.05802,7.272927 -1.064774,0.567519 -3.296855,1.394887 -4.960181,1.838599 -4.028418,1.074624 -6.656974,2.456611 -9.247046,4.861719 -8.093415,7.515443 -8.545534,19.977506 -1.025039,28.253987 2.229138,2.453219 6.734127,4.938504 10.465737,5.773678 1.924567,0.430734 6.388743,0.187313 8.296197,-0.45238 z M 56.856564,9.8863504 c -0.506723,-0.5067231 -0.205961,-1.1257162 0.498372,-1.0256851 0.398213,0.056557 0.724025,0.3180517 0.724025,0.5811037 0,0.5112413 -0.847504,0.819475 -1.222397,0.4445814 z M 20.781607,73.142896 c 1.045361,-0.363499 3.269462,-0.945479 4.942446,-1.293291 1.672985,-0.34781 3.139822,-0.791003 3.259639,-0.98487 0.119815,-0.193869 0.304316,-0.983333 0.409998,-1.754364 0.105684,-0.771031 0.628287,-2.363762 1.161344,-3.539393 0.533057,-1.175632 0.904351,-2.242435 0.825096,-2.370673 -0.07925,-0.128237 -0.936396,-0.125648 -1.904757,0.0058 -4.41221,0.598747 -9.621441,5.144618 -10.761423,9.391023 -0.178171,0.663688 -0.213486,1.206706 -0.07847,1.206706 0.135014,0 1.10077,-0.29741 2.146133,-0.660908 z M 33.572151,60.690937 c 1.056739,-1.516099 3.474137,-3.600411 5.802545,-5.003027 l 1.792186,-1.079599 -1.825533,-0.575452 C 33.895158,52.3161 31.762972,48.514331 33.315087,43.287801 c 1.614717,-5.437351 8.527309,-7.338087 12.849802,-3.533277 1.988692,1.750519 2.835694,3.661703 2.8188,6.360381 -0.01523,2.424979 -0.648758,4.005577 -2.410631,6.013881 l -1.043836,1.18983 0.965365,-0.239816 c 1.971064,-0.489657 5.007618,-2.187545 6.733883,-3.765256 1.258485,-1.150183 2.158321,-2.383295 3.07362,-4.212007 1.1243,-2.246278 1.294187,-2.868211 1.294187,-4.737781 0,-2.848329 -1.052095,-4.977519 -3.841538,-7.774346 -5.418925,-5.433273 -13.680584,-6.622984 -20.697147,-2.980469 -4.590948,2.383304 -8.100892,6.762053 -9.433714,11.768806 -0.991558,3.7248 -0.416193,9.273857 1.348664,13.007065 1.458612,3.085405 5.707741,7.492091 7.239156,7.507579 0.285651,0.0029 0.897852,-0.537766 1.360453,-1.201454 z" + id="path964" /> + <path + style="fill:#ffffff;fill-opacity:1;stroke-width:0.176777" + d="m 18.764792,72.876192 c 0.462283,-2.096572 2.407077,-4.873168 4.676378,-6.676498 1.508434,-1.198697 4.104989,-2.521931 5.514715,-2.810361 1.186969,-0.242853 2.33359,-0.246637 2.33359,-0.0077 0,0.101181 -0.363971,1.067093 -0.808824,2.146473 -0.444853,1.079379 -0.965548,2.680594 -1.1571,3.558255 -0.191553,0.877661 -0.381407,1.649352 -0.421899,1.71487 -0.09397,0.152045 -2.004018,0.689887 -5.020608,1.413729 -1.303662,0.312819 -2.928473,0.75861 -3.610691,0.990648 -1.691716,0.575389 -1.704451,0.572603 -1.505561,-0.329416 z" + id="path10354" /> + <path + style="fill:#ffffff;fill-opacity:1;stroke-width:0.176777" + d="m 46.934212,93.230105 c -2.94566,-0.273031 -7.504438,-2.38457 -10.399655,-4.816922 -1.084285,-0.910938 -2.847219,-3.156304 -3.786758,-4.823016 -4.415132,-7.832302 -3.13826,-17.446895 3.148621,-23.708502 2.639098,-2.62849 5.097629,-4.03642 9.290665,-5.320502 2.865288,-0.877471 4.834315,-1.635051 5.989768,-2.304556 1.381169,-0.800293 3.458458,-2.672572 4.758557,-4.28893 2.387719,-2.968549 3.198544,-5.606642 2.805426,-9.127711 C 58.333829,35.19449 56.209187,32.506911 49.232309,26.812091 47.384993,25.304235 45.41584,23.678038 44.856414,23.198319 l -1.017139,-0.872214 -2.385813,0.127783 c -1.365402,0.07313 -2.385812,0.06075 -2.385812,-0.02895 0,-0.164276 1.153821,-0.950775 2.430679,-1.656866 0.860162,-0.475662 0.905233,-0.596916 0.353553,-0.951168 -0.691213,-0.44385 -2.260866,-0.803171 -5.061044,-1.158564 -1.492933,-0.18948 -2.764751,-0.396139 -2.826262,-0.459241 -0.237363,-0.243503 1.550123,-1.56302 3.241166,-2.392619 0.97407,-0.477865 1.876756,-0.868844 2.005969,-0.868844 0.181705,0 0.208451,-0.230296 0.118052,-1.016466 -0.291172,-2.532209 -0.6157,-2.999567 -2.94839,-4.2460098 L 34.841091,8.8521253 35.761128,8.4473889 c 0.884598,-0.3891465 1.080052,-0.4030208 5.074288,-0.3601986 4.147603,0.044466 4.155526,0.043826 4.949748,-0.4000605 1.06226,-0.5936918 1.133647,-1.0726308 0.203009,-1.362002 -0.862252,-0.2681072 -5.711822,-2.5546191 -5.617745,-2.6486963 0.03784,-0.037837 1.172195,0.1372096 2.520795,0.388993 2.787838,0.5204889 5.845619,0.7423398 6.252698,0.4536514 0.388272,-0.2753507 0.08234,-0.42341 -2.013312,-0.9743618 C 46.147546,3.2862646 44.748328,2.9029543 44.021235,2.6929135 42.716587,2.3160301 42.707313,2.3092094 43.314128,2.1728848 c 0.687648,-0.154484 3.330473,-0.043225 5.741405,0.2417047 3.941081,0.4657662 7.901377,2.238506 10.018713,4.4846577 0.517793,0.5492942 1.236244,1.1505771 1.596557,1.3361843 0.837718,0.4315312 2.643976,0.6877195 3.988924,0.5657639 0.607249,-0.055063 1.318154,-0.00657 1.686691,0.1150605 0.757724,0.2500711 2.331913,1.9001881 2.793065,2.9277831 l 0.317328,0.707106 -4.720561,0.104018 c -2.596309,0.05721 -4.740449,0.116872 -4.764756,0.132583 -0.134807,0.08713 -0.01225,0.557773 0.175458,0.673782 0.120809,0.07466 1.509001,0.178796 3.08487,0.231404 1.835578,0.06128 2.939686,0.170163 3.072451,0.303001 0.301664,0.301832 -0.378253,1.183599 -1.353236,1.754977 -0.773745,0.453444 -0.794804,0.455774 -1.270079,0.140493 -0.357683,-0.237273 -0.919758,-0.337776 -2.162668,-0.386698 -2.167898,-0.08533 -7.901864,0.231339 -8.521008,0.470591 -0.262719,0.10152 -0.602848,0.426649 -0.755841,0.722507 -0.244422,0.472659 -0.247392,0.597449 -0.02447,1.028527 0.419193,0.810626 3.00601,3.159006 6.471309,5.874821 4.005599,3.139255 5.357566,4.398916 6.498515,6.054819 1.12685,1.635441 1.674324,2.728808 2.192165,4.378002 0.374434,1.192476 0.414905,1.648993 0.414905,4.680124 0,2.874133 -0.05966,3.626576 -0.413482,5.214913 -1.093825,4.910268 -3.256693,8.891433 -6.735643,12.398221 -2.369186,2.388143 -3.938436,3.346904 -9.687386,5.918681 -5.79933,2.594317 -7.815406,3.740813 -9.12278,5.187921 -2.221242,2.458649 -2.885127,7.351365 -1.40708,10.369931 1.121633,2.290674 3.58505,4.550632 5.65834,5.191005 1.424559,0.440003 4.095893,0.480183 5.615172,0.08446 3.124028,-0.813707 5.654604,-3.491769 6.53322,-6.913989 0.346383,-1.349169 0.357309,-3.906626 0.02207,-5.166165 -0.809749,-3.042345 -3.445523,-5.698358 -6.681692,-6.733 -0.364602,-0.116568 -0.662913,-0.26737 -0.662913,-0.335114 0,-0.06774 0.775608,-0.508132 1.723573,-0.978643 0.947965,-0.470509 2.638392,-1.393299 3.756505,-2.050645 2.606986,-1.532666 4.139351,-2.300199 4.592306,-2.300199 0.478294,0 2.166648,1.733709 3.33691,3.426551 6.207743,8.979822 4.445644,21.073723 -3.99328,27.407238 -1.61122,1.209241 -4.024544,2.490885 -5.817127,3.089302 -1.929901,0.644257 -5.076341,0.937266 -7.576363,0.70554 z M 57.8176,9.9816635 c 0.778783,-0.416792 0.08911,-1.3835647 -0.823581,-1.1544923 -0.293882,0.07376 -0.425477,0.2314974 -0.425477,0.5100062 0,0.7295866 0.554982,1.0159446 1.249058,0.6444861 z" + id="path10356" /> + <path + style="fill:#ffffff;fill-opacity:1;stroke-width:0.176777" + d="m 31.289475,61.439976 c -1.772107,-0.939022 -4.867229,-4.479811 -6.112599,-6.992754 -1.942714,-3.920062 -2.48877,-9.733256 -1.284236,-13.671694 1.849823,-6.048324 6.89648,-10.87488 13.199453,-12.623785 1.144875,-0.317671 1.840115,-0.376749 4.45043,-0.378174 2.876145,-0.0016 3.204628,0.03247 4.673262,0.48423 3.068101,0.943771 5.260853,2.262606 7.531159,4.529631 2.887943,2.883766 3.79462,4.867086 3.677042,8.043383 l -0.06792,1.834932 -1.094409,2.197797 c -1.638041,3.28953 -3.637346,5.273481 -7.062425,7.008192 -1.158172,0.586584 -3.072227,1.296873 -3.186585,1.182514 -0.03744,-0.03744 0.261638,-0.449007 0.664608,-0.914602 1.722613,-1.990325 2.313276,-3.527236 2.318592,-6.032991 0.0041,-1.919486 -0.341469,-3.270548 -1.163588,-4.549653 -2.512289,-3.908773 -7.694122,-5.010893 -11.544233,-2.455335 -1.533797,1.018075 -2.552385,2.480897 -3.118882,4.479109 -1.433525,5.056484 0.740721,8.718579 6.281798,10.580467 l 1.425705,0.47906 -1.613861,1.023091 c -2.290298,1.451912 -4.172993,3.042691 -5.554978,4.693669 -0.662292,0.791201 -1.328836,1.422913 -1.496801,1.418578 -0.166546,-0.0043 -0.581234,-0.155346 -0.921529,-0.335665 z" + id="path10358" /> + </g> +</svg> diff --git a/static/pix/xmpp.svg b/static/pix/xmpp.svg new file mode 100644 index 0000000..c9d7536 --- /dev/null +++ b/static/pix/xmpp.svg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) --> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xml:space="preserve" viewBox="0 0 200 200" width="200px" height="200px" x="0px" y="0px" enable-background="new 0 0 200 200"> + +<linearGradient id="SVGID_right_" y2="1.279e-13" gradientUnits="userSpaceOnUse" x2="-1073.2" gradientTransform="translate(1196.604,37.368977)" y1="126.85" x1="-1073.2"> + <stop stop-color="#1b3967" offset=".011" /> + <stop stop-color="#13b5ea" offset=".467" /> + <stop stop-color="#002b5c" offset=".9945" /> +</linearGradient> + +<linearGradient id="SVGID_left_" y2="1.279e-13" gradientUnits="userSpaceOnUse" x2="-1073.2" gradientTransform="matrix(-1,0,0,1,-994.78801,37.367977)" y1="126.85" x1="-1073.2"> + <stop stop-color="#1b3967" offset=".011" /> + <stop stop-color="#13b5ea" offset=".467" /> + <stop stop-color="#002b5c" offset=".9945" /> +</linearGradient> + +<path d="m 151.80512,51.557978 c 0.077,1.313 -1.787,0.968 -1.787,2.293 0,38.551002 -46.558,97.366012 -91.687985,108.730012 v 1.639 C 118.28313,158.69999 186.89012,96.41998 188.40012,37.369977 l -36.599,14.189001 z" style="fill:url(#SVGID_right_)" /> +<path d="m 133.67312,56.300978 c 0.076,1.313 0.12,2.63 0.12,3.957 0,38.551002 -30.69898,90.497012 -75.826985,101.860012 v 1.639 c 59.044005,-2.79 105.809995,-63.02401 105.809995,-109.200012 0,-2.375 -0.128,-4.729 -0.371,-7.056 l -29.73,8.798 z" style="fill:#e96d1f" /> +<path d="m 163.69112,46.951978 -7.61699,2.722 c 0.041,0.962 0.066,2.254 0.066,3.225 0,41.219002 -37.271,98.204012 -87.271995,107.120012 -3.24501,1.088 -7.53801,2.077 -10.932,2.931 v 1.638 C 123.19013,159.02799 169.03613,92.72198 163.69612,46.947978 Z" style="fill:#d9541e" /> + +<path d="m 50.011,51.556978 c -0.077,1.313 1.787,0.968 1.787,2.293 0,38.551002 46.558007,97.366012 91.68799,108.730012 v 1.639 C 83.533,158.69899 14.926,96.41898 13.416,37.368977 l 36.599,14.189001 z" style="fill:url(#SVGID_left_)" /> +<path d="m 68.143,56.299978 c -0.076,1.313 -0.12,2.63 -0.12,3.957 0,38.551002 30.698995,90.497012 75.82699,101.860012 v 1.639 C 84.806,160.96599 38.04,100.73198 38.04,54.555978 c 0,-2.375 0.128,-4.729 0.371,-7.056 l 29.73,8.798 z" style="fill:#a0ce67" /> +<path d="m 38.125,46.950978 7.617,2.722 c -0.041,0.962 -0.066,2.254 -0.066,3.225 0,41.219002 37.271,98.204012 87.27199,107.120012 3.245,1.088 7.538,2.077 10.932,2.931 v 1.638 C 78.626,159.02699 32.78,92.72098 38.12,46.946978 Z" style="fill:#439639" /> + +</svg> diff --git a/static/pix/xmr.png b/static/pix/xmr.png Binary files differnew file mode 100644 index 0000000..00cfa96 --- /dev/null +++ b/static/pix/xmr.png diff --git a/static/pix/xmr.svg b/static/pix/xmr.svg new file mode 100644 index 0000000..ed940b8 --- /dev/null +++ b/static/pix/xmr.svg @@ -0,0 +1 @@ +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3756.09 3756.49"><title>monero</title><path d="M4128,2249.81C4128,3287,3287.26,4127.86,2250,4127.86S372,3287,372,2249.81,1212.76,371.75,2250,371.75,4128,1212.54,4128,2249.81Z" transform="translate(-371.96 -371.75)" style="fill:#fff"/><path id="_149931032" data-name=" 149931032" d="M2250,371.75c-1036.89,0-1879.12,842.06-1877.8,1878,0.26,207.26,33.31,406.63,95.34,593.12h561.88V1263L2250,2483.57,3470.52,1263v1579.9h562c62.12-186.48,95-385.85,95.37-593.12C4129.66,1212.76,3287,372,2250,372Z" transform="translate(-371.96 -371.75)" style="fill:#f26822"/><path id="_149931160" data-name=" 149931160" d="M1969.3,2764.17l-532.67-532.7v994.14H1029.38l-384.29.07c329.63,540.8,925.35,902.56,1604.91,902.56S3525.31,3766.4,3855,3225.6H3063.25V2231.47l-532.7,532.7-280.61,280.61-280.62-280.61h0Z" transform="translate(-371.96 -371.75)" style="fill:#4d4d4d"/></svg> diff --git a/static/pix/yarr.svg b/static/pix/yarr.svg new file mode 100644 index 0000000..bedae7c --- /dev/null +++ b/static/pix/yarr.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-anchor"><circle cx="12" cy="5" r="3"/><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/></svg> diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..00b5710 --- /dev/null +++ b/static/style.css @@ -0,0 +1,333 @@ +/* Since this site is about teaching web concepts, even this file is a learning + * opportunity. */ + +body { + color: beige ; + background: #111 ; + margin-bottom: 200px ; + font-family: sans-serif ; +} + +h1 { + text-align: center ; + color: lightgreen ; +} + +header h1 { + font-size: 40px ; +} + +h2 { + text-align: center ; + color: deeppink ; + font-size: 24pt ; + border-bottom: dashed #ddd 1px ; + max-width: 500px ; + margin: 1em auto ; +} + +h3 { + color: gold ; + clear: both ; +} + +/* "a" is for links. */ +a { + color: lightblue ; +} + +/* The "hover" option, which can be used with pretty much anything, allows you + * to set different settings if someone hovers over something with their mouse. + * */ +a:hover { + color: white ; +} + +dt { + font-weight: bold ; +} + +/* code and pre are for formatting monospace text commands. Use code generally, + * but pre is for separate code blocks. pre is also sensitive to whitespace, + * unlike most of HTML. */ +code { + border-radius: 5px ; +} +pre { + background: #111222 ; + border: 1px solid lime ; + border-radius: 20px ; + padding: 1em ; + white-space: pre-wrap; + overflow-wrap: break-word ; + max-width: 600px ; + margin: auto ; +} + +.wide { max-width: inherit ; } + +p img, li img, h1 img, h2 img, h3 img, h4 img, dt img, .inline { + vertical-align: middle ; + max-width: 1em; + max-height: 1em; + border: none ; + display: inline ; +} + +p img, li img, h1 img, h2 img, h3 img, h4 img, dt img, .inline { + vertical-align: middle ; + max-width: 1em; + max-height: 1em; + border: none ; + display: inline ; +} + +img { + max-width: 90% ; + margin: auto ; + display: block ; + border: solid 5px beige ; +} +.titleimg { + border: none ; + height: 150px ; +} +strong { + color: orange ; +} + +footer { + text-align: center ; + font-variant: small-caps ; + clear: both ; + padding: 2em 0 ; +} +footer li { + display: inline-block ; + padding: 0 .5em ; + font-size: x-large ; +} +footer li:hover { + background: lightblue ; +} + +nav { font-size: small ;} + +footer { font-size: large ; } + +nav ul, footer ul, #taglist { + padding: 0; +} + +main { + margin: auto ; +} + +/* asides are used for minor tangential notes. I have them shrunk down in + * softer colors in a box with soft corners (border-radius). */ + +aside { + border: solid 1px black ; + border-radius: 20px ; + padding: 0 1em 0 1em ; + font-size: small ; +} + +aside p { + color: gray ; +} + +aside code { + color: green ; +} + +/* .callout here is refencing any aside given the class name callout + * An example being: <aside class="callout"> */ +aside.callout { + border: solid 1px orange; +} + +.cnp { + width: 100% ; + +} + +/* This "@media" block defines rules that will only be applied when the minimum + * width of the screen is 55em or greater. In essence, they are settings that + * only apply on normal widescreens, but *not* phones and low res monitors. + * Since we have more room on widescreens, we change a couple things. */ + +@media (min-width: 55em) { + + aside { + margin: 0 30px 0 30px; + } + + .resright, .disappear { + display: block ; + float: right; + padding: 20px ; + clear: both ; + max-height: 400px ; + max-width: 300px ; + } + + header { max-width: 900px ; margin: auto;} + main { max-width: 850px ; } +} + +.ll { + font-size: large ; + line-height: 1.3em ; + max-width: 600px; + margin: auto ; + display: block ; +} + +.ll dt { + display: inline-block ; + width: 6em ; + background: gray ; + max-width: 30% ; +} + +.ll dd { + display: inline ; + background: blue ; + max-width: 60% ; +} + +.ll dd:after { + display:block; + content: '' ; +} + + +/* These settings are for the cryptocurrency donation QR codes and info on the + * main page. */ +.qr { max-width: 150px ; padding: 10px; border: none; } +.cryptocontainer { + display: flex ; + flex-wrap: wrap ; + justify-content: center ; +} +.cryptoinfo { + max-width: 350px ; + text-align: center ; + padding-left: 10px ; + padding-right: 10px ; +} +.cryptoinfo code,.crypto { + font-size: small ; + overflow-wrap: break-word ; +} + +/* The "Next Article" Button changes color and also has a 👉 automatically + * added to its front. */ + +@-webkit-keyframes next { + 0% {color: yellow ;} + 100% {color: lightblue} +} + +.prev { + font-size: large ; + text-align: center ; + margin: auto ; + display: block ; + font-weight: bold ; + padding: 1em ; +} + +.prev:before { + content: "👈" ; +} + +.next a { + color: inherit ; +} + +.next { + -webkit-animation:next 1s infinite alternate ; + font-size: xx-large ; + text-align: center ; + margin: auto ; + display: block ; + font-weight: bold ; + padding: 1em ; +} + +#servicelist { + text-align: center ; +} + +.next:before { + content: "👉" ; +} + +#servicelist { + padding-left: 0 ; +} + +#servicelist li { + display: inline-block ; + height: 150px ; + width: 150px ; + position: relative ; +} + +#servicelist img { + height: 80% ; + width: 80% ; + max-height: none ; + max-width: none ; + position: absolute ; + left: 50% ; + transform: translateX(-50%); +} + +#servicelist .title, #servicelist li:hover .desc { + display: block ; + position: absolute ; + color: white ; + width: 100% ; + text-align: center ; + top: 50%; + transform: translateY(-50%); + border-radius: 1em ; + font-size: large ; + +} + +.left { + width: 45% ; + float: left ; + clear: both ; +} + +.right { + width: 45% ; + float: right ; +} + +br { + clear: both; +} + +#servicelist .title { + font-size: xx-large ; + background-color: rgba(3,3,3,0.6) ; +} +#servicelist li:hover .desc { + background-color: rgba(3,3,3,0.9) ; +} + +#servicelist li:hover .title, .desc, .tags { + display: none ; +} + +mark { + background: unset ; + color: orange ; + font-weight: bold ; +} diff --git a/themes/lugo/.github/workflows/upload.yml b/themes/lugo/.github/workflows/upload.yml new file mode 100644 index 0000000..13acfb8 --- /dev/null +++ b/themes/lugo/.github/workflows/upload.yml @@ -0,0 +1,32 @@ +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push to master (including merged PRs) + push: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + update: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Updating website. + uses: appleboy/ssh-action@master + with: + host: lukesmith.xyz + username: lugo + key: ${{ secrets.lugo_ssh }} + passphrase: ${{ secrets.lugo_pass }} + port: 22 + script: | + cd /var/www/lugo + git stash + git pull --force origin master diff --git a/themes/lugo/README.md b/themes/lugo/README.md new file mode 100644 index 0000000..a39a9e8 --- /dev/null +++ b/themes/lugo/README.md @@ -0,0 +1,21 @@ +# Luke's Hugo Theme + +A simple Hugo theme I plan on using for my personal website, [Based.Cooking](https://based.cooking) and [LandChad.net](https://landchad.net). + +## get started + +```sh +hugo new site new-site +cd new-site +git clone https://github.com/lukesmithxyz/lugo themes/lugo +echo "theme = 'lugo'" >> config.toml +cp themes/lugo/static/style.css static/ +``` + +## stuff + +- Makes one RSS feed for the entire site at `/index.xml` +- Stylesheet is in `/style.css` and includes some important stuff for partials. +- If a post is tagged, links to the tags are placed at the bottom of the post. +- `nextprev.html` adds links to the Next and Previous articles to the bottom of a page. +- `taglist.html` links all tags an article is tagged to for related content. diff --git a/themes/lugo/archetypes/default.md b/themes/lugo/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/themes/lugo/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/themes/lugo/config.toml b/themes/lugo/config.toml new file mode 100644 index 0000000..e884199 --- /dev/null +++ b/themes/lugo/config.toml @@ -0,0 +1,17 @@ +title = "Website Name" +baseURL = 'https://example.org' +languageCode = 'en-us' + +[params] + # "relatedtext" is the text that appears above the tag list at the bottom of pages. + relatedtext = "Related" + favicon = "/favicon.ico" + + #list items + datesinlist = true + authorsinlist = true + + #footer items + nextprev = true + taglist = true + showrss = true
\ No newline at end of file diff --git a/themes/lugo/layouts/_default/baseof.html b/themes/lugo/layouts/_default/baseof.html new file mode 100644 index 0000000..57e17ce --- /dev/null +++ b/themes/lugo/layouts/_default/baseof.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html lang="{{ .Site.Language }}"> +<head> + <title>{{ if not .IsHome }}{{ .Title | title }} | {{ end }}{{ .Site.Title }}</title> + <link rel="canonical" href="{{ .Site.BaseURL }}"> + <link rel='alternate' type='application/rss+xml' title="{{ .Site.Title }} RSS" href='/index.xml'> + <link rel='stylesheet' type='text/css' href='/style.css'> + {{ with .Site.Params.favicon }}<link rel="icon" href="{{ . }}"> + {{ end -}} + <meta name="description" content="{{ with .Params.description }}{{ . }}{{ else }}{{ .Summary }}{{ end }}"> + {{ if isset .Params "tags" }}<meta name="keywords" content="{{ with .Params.tags }}{{ delimit . ", " }}{{ end }}"> + {{ end -}} + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="robots" content="index, follow"> + <meta charset="utf-8"> +</head> +<body> +{{ if .Site.Menus.main }}{{ partial "nav.html" . }}{{ end -}} +<main> +<header><h1 id="tag_{{ .Title }}">{{ block "title" . }}{{ end }}</h1></header> +<article> +{{ block "main" . }} +{{ .Content }} +{{ end }} +{{ if .Param "nextprev" }}{{ partial "nextprev.html" . -}}{{ end -}} +{{ if .Param "taglist" }}{{ partial "taglist.html" . }}{{ end -}} +</article> +</main> +{{ block "footer" . }} +<footer> + <a href="{{ .Site.BaseURL }}">{{ .Site.BaseURL }}</a> + {{- if .Param "showrss" }}<br><br><a href="/index.xml"><img src="/rss.svg" style="max-height:1.5em" alt="RSS Feed" title="Subscribe via RSS for updates."></a>{{ end }} +</footer> +{{ end }} +</body> +</html> diff --git a/themes/lugo/layouts/_default/list.html b/themes/lugo/layouts/_default/list.html new file mode 100644 index 0000000..601fc08 --- /dev/null +++ b/themes/lugo/layouts/_default/list.html @@ -0,0 +1,20 @@ +{{ define "title" -}} +{{ .Title | title }} +{{- end }} +{{ define "main" -}} +{{ .Content }} +<ul> +{{- range.Pages }} +<li> + {{- if .Param "datesinlist" }}<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">{{ .Date.Format "2006 Jan 02" }}</time> – {{ end -}} + <a href="{{ .RelPermalink }}">{{ .Title }}</a> + {{- if .Param "authorsinlist" }} + {{ with .Params.authors }} + by + {{ delimit . ", " " and " }} + {{end}} + {{ end -}} +</li> +{{- end }} +</ul> +{{- end }} diff --git a/themes/lugo/layouts/_default/rss.xml b/themes/lugo/layouts/_default/rss.xml new file mode 100644 index 0000000..38dbe3d --- /dev/null +++ b/themes/lugo/layouts/_default/rss.xml @@ -0,0 +1,26 @@ +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>{{ .Site.Title }}</title> + <link>{{ .Permalink }}</link> + <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description> + <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }} + <language>{{.}}</language>{{end}}{{ with .Site.Author.email }} + <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }} + <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }} + <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }} + <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }} + {{ with .OutputFormats.Get "RSS" }} + {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} + {{ end }} + {{ range .Site.RegularPages }} + <item> + <title>{{ .Title }}</title> + <link>{{ .Permalink }}</link> + <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate> + {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}} + <guid>{{ .Permalink }}</guid> + <description>{{- .Content | html -}}</description> + </item> + {{ end }} + </channel> +</rss> diff --git a/themes/lugo/layouts/_default/single.html b/themes/lugo/layouts/_default/single.html new file mode 100644 index 0000000..56c5a11 --- /dev/null +++ b/themes/lugo/layouts/_default/single.html @@ -0,0 +1,3 @@ +{{ define "title" -}} +{{ .Title }} +{{- end }} diff --git a/themes/lugo/layouts/partials/nav.html b/themes/lugo/layouts/partials/nav.html new file mode 100644 index 0000000..a7318fe --- /dev/null +++ b/themes/lugo/layouts/partials/nav.html @@ -0,0 +1,8 @@ +<nav> + <ul> + {{- $sec := .Page.Section }}{{ $file := .File.TranslationBaseName -}} + {{ range.Site.Menus.main.ByWeight }}{{ $base := path.Base .URL }} + <li><a {{ if or ( eq $sec $base ) ( eq $file $base ) ( and (eq $sec "") ( eq $file "_index") (eq $base "/") ) }}class="menuactive" {{ end }}href="{{ .URL }}"><span class=pre>{{ .Pre }}</span><span class=menuname>{{ .Name }}</span></a></li> + {{- end }} + </ul> +</nav> diff --git a/themes/lugo/layouts/partials/nextprev.html b/themes/lugo/layouts/partials/nextprev.html new file mode 100644 index 0000000..099f16d --- /dev/null +++ b/themes/lugo/layouts/partials/nextprev.html @@ -0,0 +1,10 @@ +{{ if or .Next .Prev -}} +<div id="nextprev"> +{{- with .Prev }} +<a href="{{ .RelPermalink}}"><div id="prevart">Previous:<br>{{.Title}}</div></a> +{{ end -}} +{{- with .Next -}} +<a href="{{ .RelPermalink}}"><div id="nextart">Next:<br>{{.Title}}</div></a> +{{ end -}} +</div> +{{ end -}} diff --git a/themes/lugo/layouts/partials/taglist.html b/themes/lugo/layouts/partials/taglist.html new file mode 100644 index 0000000..757db6f --- /dev/null +++ b/themes/lugo/layouts/partials/taglist.html @@ -0,0 +1,13 @@ + {{- if isset .Params "tags" -}} + {{- $tagsLen := len .Params.tags -}} + {{- if gt $tagsLen 0 -}} + <div style="clear:both" class=taglist> + {{- with .Site.Params.relatedtext }}{{ . }}<br>{{ end -}} + {{- range $k, $v := .Params.tags -}} + {{- $url := printf "tags/%s" (. | urlize | lower) -}} + <a id="tag_{{ . | lower }}" href="{{ $url | absURL }}">{{ . | title }}</a> + {{- if lt $k (sub $tagsLen 1) }} · {{ end -}} + {{- end -}} + </div> + {{- end -}} + {{- end }} diff --git a/themes/lugo/layouts/shortcodes/hidvid.html b/themes/lugo/layouts/shortcodes/hidvid.html new file mode 100644 index 0000000..14f592d --- /dev/null +++ b/themes/lugo/layouts/shortcodes/hidvid.html @@ -0,0 +1,10 @@ +<details> + <summary>Click to reveal video.</summary> +<iframe src="{{ index .Params 0 }}" + loading="lazy" + sandbox="allow-same-origin allow-scripts allow-popups" + allowfullscreen frameborder="0" + class="embvid" + title="Embedded Video"> +</iframe> +</details> diff --git a/themes/lugo/layouts/shortcodes/img.html b/themes/lugo/layouts/shortcodes/img.html new file mode 100644 index 0000000..ff7959b --- /dev/null +++ b/themes/lugo/layouts/shortcodes/img.html @@ -0,0 +1,20 @@ +<!-- + class: class of the figure + link: url the image directs to + alt: alternative text + caption: caption + mouse: what the image says when moused over ("title" in HTML) +--> +<figure {{ with .Get "class" }}class="{{.}}"{{ end -}}> + {{- with .Get "link"}}<a href="{{.}}">{{ end -}} + <img src="{{ .Get "src" }}" + {{- with .Get "mouse" }} title="{{.}}"{{ end -}} + {{- with .Get "alt" }} alt="{{.}}"{{ end -}} + > + {{- if .Get "link"}}</a>{{ end -}} + {{- with .Get "caption" -}} + <figcaption> + {{- . -}} + </figcaption> + {{- end -}} +</figure> diff --git a/themes/lugo/layouts/shortcodes/tagcloud.html b/themes/lugo/layouts/shortcodes/tagcloud.html new file mode 100644 index 0000000..0cf0118 --- /dev/null +++ b/themes/lugo/layouts/shortcodes/tagcloud.html @@ -0,0 +1,3 @@ +{{ if isset .Site.Taxonomies "tags" }}{{ if not (eq (len .Site.Taxonomies.tags) 0) }} <ul id="tagcloud"> + {{ range $name, $items := .Site.Taxonomies.tags }}{{ $url := printf "%s/%s" "tags" ($name | urlize | lower)}}<li><a href="{{ $url | absURL }}" id="tag_{{ $name }}">{{ $name | title }}</a></li> + {{ end }}</ul>{{ end }}{{ end }} diff --git a/themes/lugo/layouts/shortcodes/vid.html b/themes/lugo/layouts/shortcodes/vid.html new file mode 100644 index 0000000..4c612fe --- /dev/null +++ b/themes/lugo/layouts/shortcodes/vid.html @@ -0,0 +1,6 @@ +<iframe src="{{ index .Params 0 }}" + loading="lazy" + sandbox="allow-same-origin allow-scripts allow-popups" + allowfullscreen frameborder="0" + title="Embedded Video"> +</iframe> diff --git a/themes/lugo/static/rss.svg b/themes/lugo/static/rss.svg new file mode 100644 index 0000000..dfda038 --- /dev/null +++ b/themes/lugo/static/rss.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 455.731 455.731" style="enable-background:new 0 0 455.731 455.731;" xml:space="preserve"><g><rect x="0" y="0" style="fill:#F78422;" width="455.731" height="455.731"/><g><path style="fill:#FFFFFF;" d="M296.208,159.16C234.445,97.397,152.266,63.382,64.81,63.382v64.348 c70.268,0,136.288,27.321,185.898,76.931c49.609,49.61,76.931,115.63,76.931,185.898h64.348 C391.986,303.103,357.971,220.923,296.208,159.16z"/><path style="fill:#FFFFFF;" d="M64.143,172.273v64.348c84.881,0,153.938,69.056,153.938,153.939h64.348 C282.429,270.196,184.507,172.273,64.143,172.273z"/><circle style="fill:#FFFFFF;" cx="109.833" cy="346.26" r="46.088"/></g></g></svg>
diff --git a/themes/lugo/static/style.css b/themes/lugo/static/style.css new file mode 100644 index 0000000..d3b2088 --- /dev/null +++ b/themes/lugo/static/style.css @@ -0,0 +1,45 @@ +body { + font-family: sans-serif ; + background: #110000 ; + color: #ccc ; +} + +main { + max-width: 800px ; + margin: auto ; +} + +img { + max-width: 100% ; +} + +header h1 { + text-align: center ; +} + +footer { + text-align: center ; + clear: both ; +} + +/* For TAGLIST.HTML */ +.taglist { + text-align: center ; + clear: both ; +} + +/* For NEXTPREV.HTML */ +#nextprev { + /* The container for both the previous and next articles. */ +} +#prevart { + float: left ; + text-align: left ; +} +#nextart { + float: right ; + text-align: right ; +} +#nextart,#prevart { + max-width: 33% ; +} |
