Git Product home page Git Product logo

archcodes's Introduction

Archcodes

Overview

Source code (AGPL) for archcodes.com - fast parametric architecture generator focused on ease of use, design quality and privacy.

Backend

Web

Compute (3D processing) - WIP!

  • Rhino
  • Blender
  • Houdini

Frontend

Backend

Hosting

If you choose to host “on the cloud ☁️” here are my recommmendations for privacy-oriented providers. [2023-10-19 Thu]

nameLocationPrice
1984.hostingIceland77 € / year (27.49 € for 1st year)
njal.laSweden (Malmo)15 € / month
exoscale.comEurope11.93 € / month

Other recommendations Stack Overflow 2023 Survey

Base setup

Preliminaries

  • Debian 12
  • first login with public ssh key shared with the hosting provider
  • first login as root
  • ownership of a DNS domain

Login to the server

ssh root@<SERVER-IP>

Update and upgrade packages

apt update && apt upgrade -y

Add new sudo user

adduser admin --gecos ""
usermod -aG sudo admin

Transfer ssh key

cp -r /root/.ssh /home/admin
chown -R admin:admin /home/admin/.ssh

Logout of root and login as admin.

Remove message on login

touch .hushlogin

Remove root password and lock

sudo passwd -d root
sudo passwd -l root

Configure firewall

On Debian ufw may be already installed and preconfigured.

sudo apt install ufw -y
sudo ufw allow <CHOOSE-PORT-NUMBER-BETWEEN-1024-AND-65535>
# For example: sudo ufw allow 38461
sudo ufw enable

Configure ssh daemon

sudo vi /etc/ssh/sshd_config
Port <CHOOSE-PORT-BETWEEN-1024-AND-65535>
# For example: Port 38461

# Disable login as root 
PermitRootLogin no
# No need for Graphics on a server
X11Forwarding no
# Use cryptographic keys instead of passwords 
PasswordAuthentication no
# Only allow "admin" user to login via ssh 
# If you named your user differently change it for that name
AllowUsers admin
sudo systemctl restart sshd

⚠️ Note down the Port number.

⚠️ Before logging out make sure port number was allowed in ufw or you will be locked out.

Miscellaneous fixes

Disable passwordless sudo

# Check if this file exists
sudo cat /etc/sudoers.d/90-cloud-init-users
# Remove it
sudo rm /etc/sudoers.d/90-cloud-init-users

Disable ssh logins via password

# Check if this file exists
sudo cat /etc/ssh/sshd_config.d/50-cloud-init.conf
# Remove it
sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
# Restart ssh
sudo systemctl restart sshd

Configure fail2ban

Your server will be constantly scanned for vulnerabilities by various (good and bad) parties. Fail2Ban blocks such attempts if they reach a predefined number of unsuccessful connections.

sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vi /etc/fail2ban/jail.local

Sane defaults:

[DEFAULT]
bantime = 1000m
findtime = 100m
maxentry = 3
# In Debian 12 it became necessary to specify systemd backend explicitely.
backend = systemd

⚠ If you failed to connect more than 3 times before setting this up it may block you. Fix

sudo systemctl restart fail2ban.service

Unban your IP

⚠ Advanced Use a proxy/VPN/Tor to change your IP, reconnect to the server and unban you IP.

Tor

Start tor service or connect the Tor Browser. The easiest way to setup Tor service on desktop is to download the Tor Browser and start it. It bundles tor server and will make it available locally on port 9050.

ssh -o ProxyCommand='nc -x 127.0.0.1:9150 %h %p' <USER>@<SERVER-IP>
# check your IP
curl ifconfig.me

Unban your original IP.

Optional

Copy .bashrc

Recommended .bashrc included in this repo.

scp -P <SSH-PORT-NUMBER> <PATH-TO-THIS-REPO>/.bashrc <SERVER-IP>:

fzf

Install fzf fuzzy finder to serach command history interactively (Ctrl+R).

sudo apt install git wget -y
git clone --depth 1 https://github.com/junegunn/fzf.git .fzf
./.fzf/install

Extras

sudo apt install fd-find exa bat ripgrep htop nethogs -y

Below aliases (e.g. b instead of batcat) were set in the above .bashrc file.

fd-find

Search files by name.

Example

Find all directories (-td) that have system-wg somewhere in their name. Search only in /sys/fs/cgroup.

fd -td system-wg /sys/fs/cgroup
ripgrep

Search files by contents name.

Example

Search for alias in .bashrc

rg alias .bashrc
exa

Pretty print directories.

Example

README-images/_20231019_161012screenshot.png

batcat

View file contents.

Example

View contents of .bashrc.

b .bashrc
htop

View running processes.

Example
htop
nethogs

View running network connections.

Example
nethogs -l -a -C

-l display command line -C capture TCP and UDP -a monitor all devices, even loopback/stopped ones

Dns and hostname

These may have been automatically set by your hosting provider.

Your hostname

sudo vi /etc/hostname

Server DNS

sudo vi /etc/host

127.0.1.1 hostname.example.com hostname or: <STATIC-IP> hostname.example.com hostname

Test

dnsdomainname
dnsdomainname -f
dnsdomainname --fqdn

Reboot

sudo reboot

Maintenance

Fail2ban

list banned IPs

sudo fail2ban-client status sshd
sudo zgrep 'Ban' /var/log/fail2ban.log* | b

unban IP

fail2ban-client set sshd unbanip IPADDRESSHERE

or unban all IPs

fail2ban-client unban --all

Check on unsolicited connections

journalctl -u sshd
cat /var/log/fail2ban.log

Check previous logins

last

Check for update history

zgrep . /var/log/apt/history.log*

Check uptime

uptime

Check kernel release

uname --kernel-release

Full ditro upgrade

Make sure to take snapshot/backup beforehand. It’s not always guaranteed to work.

sudo apt-get full-upgrade

Nginx

sudo apt install nginx

Add SSL

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx --domain example.com --domain subdomain.example.com --email [email protected] --agree-tos --redirect --hsts --staple-ocsp

Add domain configuration

Update root directive.

sudo vi /etc/nginx/sites-available/<DOMAIN-NAME>
mkdir /var/www/<DOMAIN-NAME>/

Fail2ban

Enable for nginx

sudo vi /etc/fail2ban/jail.local
[nginx-http-auth]
enabled  = true
sudo systemctl restart fail2ban.service

Check

sudo fail2ban-client status
sudo fail2ban-client status nginx-http-auth
sudo iptables -S | grep f2b

Security and privacy

Considerations

HTTP Headers

  • Separate for each location context. If set in server context and another header is added to a location they get erased.
  • Create a new file and include it to simplify configuration.
location / {
    include /etc/nginx/security-headers.conf;
}
sudo vi /etc/nginx/security-headers.conf
Strict Transport Security

Python-nginx-certbot plugin adds it automatically, but doesn’t include subdomains.

add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always;

“SSL stripping” is based on intercepting the first request to a website (before SSL encryption).

Content-Security-Policy

Protect against XSS (cross-site scripting). Restrict access to javascript files from other origins.

add_header Content-Security-Policy "object-src 'none'; script-src 'self'; script-src-elem 'self'; font-src self; base-uri 'self'; require-trusted-types-for 'script'" always;
X-Frame-Options
add_header X-Frame-Options "DENY" always;
X-Content-Type-Options
add_header X-Content-Type-Options "nosniff" always;
Referrer-policy
add_header Referrer-Policy "strict-origin" always;
X-XSS-Protection
add_header X-Xss-Protection "1; mode=block" always;
Cross-origin resource sharing

Allow others to use resources from your domain. No need to add this. Informational only. =add_header Access-Control-Allow-Origin “example.com”=

Feature-Policy and Permissions-Policy
add_header Feature-Policy "microphone 'none'; geolocation 'none'; camera 'none'" always;
add_header Permissions-Policy "microphone=(); geolocation=(); camera=()" always;
Test

https://securityheaders.com/

Rate limiting

Rate limits to 10 requests per second per client. Not quite sure yet how to control it “globally” and how much of it will be needed. I believe that if exceeded Nginx will send 429 code and the browser will inform the user automatically.

http {
    limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/s;
    server {
        location @proxy_to_app {
            limit_req zone=limit_zone burst=20;
            proxy_pass http://app_server;
        }
    }
}

Virtual hosts

Docs

Basics
  • There can be multiple server contexts (aka virtual servers).
  • They are evaluated first by network interface they listen on, then server_name (aka domain name).
  • server_name can also be a wildcard or a regular expression.
  • Host header field in the client’s http request is used to match server_name.
  • default_server parameter can be used to catch requests that don’t match any server.

Example

server {
    location / {
        proxy_pass http://localhost:8080/;
    }
    # match all URIs ending with .gif, .jpg, or .png
    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

Load balacing to separate compute nodes

Treat web applications like they were already compromised. Protect the rest of the infrastructure. Separate applications into isolated machines (AND containers) and use nginx to load balance requests to them.

Wireguard

You can use VPN (e.g. wireguard) to connect web server with compute nodes. Wireguard is a fast and modern VPN.

sudo apt install wireguard -y
Configuration file
sudo vi /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <YourPrivateKey>
Address = 10.0.0.1/24
ListenPort = <Port>

[Peer]
PublicKey = <PeerPublicKey>
AllowedIPs = 10.0.0.2/32
Endpoint = <PeerEndpoint>:<PeerPort>
Keys
wg genkey | tee /dev/tty | wg pubkey
Ufw
sudo ufw allow <Port>
Start
wg-quick up wg0
Systemd service
sudo systemctl enable wg-quick@wg0
Configure Nginx
upstream app_server {
    server <WIREGUARD-PEER-IP> max_fails=3;
}
Optional parameters (with default values)
  • fail_timeout: 10s
  • weight: 1
  • max_fails: 1
  • max_conns

Hide server token

sudo vi /etc/nginx/nginx.conf
http {
    server_tokens off;
}

Cache

Change cache durations between different locations. expires adds Expires HTTP header and -1 tells the clients not to cache it.

location ~ /index.html {
    expires -1;
    add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
}

Timeout

http {
    keepalive_timeout  65;
}

Serve high traffic

Docs - Optimizing the Backlog Queue

Kernel
sudo sysctl -w net.core.somaxconn=4096
net.core.somaxconn = 4096
Nginx
sudo vi /etc/nginx/sites-available/yourdomain.com
server {
    listen 80 backlog=4096;
    # ...
}

Gunicorn

Gunicorn is simpler than uWSGI for small websites. ⚠️ Gunicorn and Flask should run on a separate “Compute” server.

Install

Prefer system packages over pip (unless a specific version is needed).

sudo apt install gunicorn

docs

Configure Nginx

docs

sudo vi /etc/nginx/sites-available/<DOMAIN-NAME>
# https://docs.gunicorn.org/en/stable/deploy.html#nginx-configuration
upstream app_server {
    # fail_timeout=0 means we always retry an upstream even if it failed
    # to return a good HTTP response

    # for UNIX domain socket setups
    server <WIREGUARD-PEER-IP>:<GUNICORN-PORT> fail_timeout=0;
    # For example: server 10.0.0.2:8000 fail_timeout=0;
}

location @proxy_to_app {
    expires -1;
    add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';

    include /etc/nginx/proxy_params;
    include /etc/nginx/security-headers.conf;

    # limit max uploaded file size
    client_max_body_size 10M;

    # we don't want nginx trying to do something clever with
    # redirects, we set the Host: header in /etc/nginx/proxy_params already.
    proxy_redirect off;
    proxy_pass http://app_server;
}

location / {
           ...
           # nginx will try first static files and if it fails it will pass request to proxy
           # I thought that you can keep the =404 at the end, but then @proxy_to_app stops working
            try_files $uri $uri/ @proxy_to_app;
        }

Systemd service unit

docs

sudo vi /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
Type=notify
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
DynamicUser=yes
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/flask
ExecStart=/usr/bin/gunicorn app:app --workers 2
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Systemd TCP socket unit

sudo vi /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=<WIREGUARD-PEER-IP>:<GUNICORN-PORT>
# For example: ListenStream=10.0.0.2:8000
# Accept=yes
[Install]
WantedBy=sockets.target
sudo systemctl enable --now gunicorn.socket

Ufw

sudo ufw allow from 10.0.0.1 to 10.0.0.2 port 8000

Flask

Deploy

Permissions

Add executable permissions to app.py.

chmod +x <FLASK-ROOT>/app.py

Run

rsync -avzhP -e "ssh -p <COMPUTE-NODE-SSH-PORT>" <PATH-TO-FLASK-ROOT> <USERNAME>@<SERVERNAME>:/srv/flask/
Example
rsync -avzhP -e "ssh -p 12345" /home/user/archcodes/flask/ [email protected]:/srv/flask/

Security

docs

Cross-Site Request Forgery

You don’t need to mitigate against CSRF if you don’t keep user sessions. If you do use “Same-Site Cookies”.

File Validation

.obj files

PyWavefront

Filename sanitization

Removing special characters, spaces and directory traversal attempts (e.g. “../”).

Frontend

Hugo

Fast static site generator.

Deploy

Remove previous build

Hugo doesn’t automatically clean previous build.

rm -rf /home/user1/archidecks.com/public

Build website

hugo -s /home/user1/archidecks.com

Pipeline

Permissions

Change <STATIC-FILES-LOCATION> permissions from root to your user.

Example

chown admin: /var/www/archcodes.com

Run
rm -rf <PATH-TO-HUGO-BUILD> \
    && hugo -s <PATH-TO-HUGO-ROOT> \
    && rsync -avzhP -e "ssh -p <SSH-PORT>" <PATH-TO-HUGO-BUILD> <USERNAME>@<SERVERNAME>:<STATIC-FILES-LOCATION>
Example
rm -rf /home/user/archcodes/public \
    && hugo -s /home/user/archcodes
    && rsync -avzhP -e "ssh -p 12345" /home/user/archcodes/public/ [email protected]:/var/www/archcodes.com/

Develop

cd <PATH-TO-HUGO-ROOT> hugo server

Ox-hugo

Org-mode to hugo markdown converter.

Update .md files on save

org-hugo-auto-export-mode Updates only subtrees that changed.

Export all subutrees

org-hugo-export-to-md

archcodes's People

Contributors

daniel-archi avatar danielkrajnik avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.