System information: Debian GNU/Linux 12 (bookworm)
Installing#
Oh My Zsh#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| apt-get update
# install ZSH
# apt-get update
apt install zsh -y
zsh --version # Expected result: zsh 5.0.8 or more recent.
# zsh 5.9 (x86_64-debian-linux-gnu)
chsh -s $(which zsh) # set zsh as default shell
# sudo chsh -s /bin/zsh <myUserName>
# new session
echo $SHELL # test
# /usr/bin/zsh
# install git
apt install git -y
git version
# git version 2.39.2
# install Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# install plugins
## zsh-autosuggestions
## https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md#oh-my-zsh
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
## add zsh-autosuggestions to the list of plugins (~/.zshrc)
source ~/.zshrc
|
Docker#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # https://docs.docker.com/engine/install/debian/#install-using-the-repository
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# install the latest version
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# verify that the installation
sudo docker run hello-world
docker version
# ...
# Version: 24.0.6
# ...
|
HTTPS#
Register and auto-renew SSL certificates with acme.sh
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # install acm.sh (change email)
curl https://get.acme.sh | sh -s email=my@example.com
acme.sh --version
# https://github.com/acmesh-official/acme.sh
# v3.0.7
crontab -l # a cron job is automatically set up
# run every day of every month at 7:19 PM
# 7 19 * * * "/$USER/.acme.sh"/acme.sh --cron --home "/$USER/.acme.sh" > /dev/null
# add DNS records on CloudFlare
# @ and www
# https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA
# register an account from ZeroSSL.com CA to issue free SSL certificates
## email must be the same as the one used to register the account
acme.sh --register-account -m my@example.com --server zerossl
# https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode
# https://github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf
# acm.sh with DNS API
# CloudFlare Multiple DNS zones (change CF_Account_ID and CF_Token)
export CF_Account_ID="xxx"
export CF_Token="xxx"
acme.sh --issue --dns dns_cf -d example.com -d "*.example.com" --force
|
NGINX#
Set up NGINX to serve the website.
- Turn off Clouflare proxy for the domain.
nginx.conf
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| # flush DNS cache if necessary
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name www.exampleho.com;
return 301 $scheme://exampleho.com$request_uri;
}
server {
listen 443 ssl;
server_name www.exampleho.com;
ssl_certificate /etc/ssl/fullchain.cer;
ssl_certificate_key /etc/ssl/exampleho.com.key;
return 301 https://exampleho.com$request_uri;
}
server {
listen 80;
server_name exampleho.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name exampleho.com;
ssl_certificate /etc/ssl/fullchain.cer;
ssl_certificate_key /etc/ssl/exampleho.com.key;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ =404;
}
}
server {
server_name _;
listen 80 default_server;
return 404;
}
# https visits to non-configured domains cannot be redirected to 404 page using similar methods
# (GPT: When a client makes a request over HTTPS, the SSL handshake happens before the HTTP request is processed. This means that the certificate for example.com is being used, even if the request is for abc.example.com.)
}
|
docker-compose-nginx.yaml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
| version: '3'
services:
nginx:
image: nginx:mainline-alpine3.18
container_name: nginx
volumes:
- ~/hosting/nginx.conf:/etc/nginx/nginx.conf
- ~/.acme.sh/exampleho.com_ecc:/etc/ssl
- ~/resumes:/resumes
- ~/hosting/homepage:/usr/share/nginx/html
ports:
- 80:80
- 443:443
|
Github Actions for Automatic Deployment#
Github repo - Settings - Actions - Runners - New self-hosted runner:
1
2
3
4
5
6
7
8
9
10
|
# export RUNNER_ALLOW_RUNASROOT="1"
# This runner will have the following labels: 'self-hosted', 'Linux', 'X64'
./svc.sh install
./svc.sh start
./svc.sh status
# ./svc.sh stop
# https://docs.github.com/en/free-pro-team@latest/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service
|
Add VPS public key to Github SSH keys:
1
2
3
4
5
6
7
8
9
| # https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent?platform=linux
# generate SSH key pair on VPS
ssh-keygen -t ed25519 -C "yourmai_el@example.com"
# add to Github SSH keys
# pull the repo to VPS first
git clone --recursive <repo_name>
git clone --recursive git@github.com:funfungho/abitinterference.git
|
Github workflow config:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| name: CI
on:
# Triggers the workflow on push or pull request events but only for the "main" branch
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
# 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"
build:
# The type of runner that the job will run on
runs-on: self-hosted
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Run remote build
run: cd ~/<repo_name> && git pull --recurse-submodules && . ~/<repo_name>/auto_deploy.sh
# auto_deploy.sh
# cd ~/<repo_name>
# rm -rf ~/<repo_name>/public && hugo
# cd ~/hosting && docker compose -f docker-compose-nginx.yaml restart
|