- Introduction
- Domain -> Server | Google
- Hosting -> Docker | Teamspeak | Minecraft | PostgreSQL | pgAdmin4
- Security -> SSL-Certificate
- Website -> GitHub-Repository | DockerHub-Repository | GitHub-Actions | Deployment-Script
As full-stack-developer you need as well to know how to host software. For example infrastructure of website but as well other software like Teamspeak3 or Minecraft. Aim of documentation is to host these software with low budget and high functionality.
Domain suadin.de and Server 81.169.247.92 are currently managed in strato. Need setup to connect both:
- add on Domain for DNS properties the Server IP as A-Record [source]
- add on Server the Domain as DNS-Reverse [source]
- Login to your google account, goto domain verification, add domain suadin.de
- proof domain ownership: select strato, create subdomain
CNAME-Target
, configure CNAME-Record withCNAME-Target
Server has Operating System (OS) Ubuntu 18.04 LTS 64bit. Pre-Installs: sudo apt-get install screen
, sudo apt-get install nano
- login as root,
apt update
,apt upgrade
,adduser $user_name
,usermod -aG sudo $user_name
,su $user_name
,cd ~
- main steps on next capters
exit
,sudo deluser $user_name sudo
,chown -hR $user_name:$user_name /home/$user_name
,exit
- follow step 1 of guide [source]
- follow step 2 but with slidely different commands:
sudo gpasswd -a docker docker
,sudo service docker restart
- start docker in screen:
screen -d -m bash -c "docker run -p 8080:80 docker/getting-started"
, check: http://suadin.de:8080
- download/unpack/accept-license with guide [source]
- add into autostart:
nano /etc/crontab
-> add@reboot teamspeak3 /home/teamspeak3/teamspeak3-server_linux_amd64/ts3server_startscript.sh
- grant/start script:
chmod +x ts3server_startscript.sh
,sudo chown -hR teamspeak3:teamspeak3 /home/teamspeak3
,./ts3server_startscript.sh start
- follow guide to setup new world [source]
- overwrite files with existing world via WinSCP
- add into autostart:
nano /etc/crontab
-> add@reboot minecraft /usr/bin/screen -dmS minecraft-screen /home/minecraft/start.sh
- folow install guide [source]
- create/grant database/user:
sudo -i -u postgres
,psql
,CREATE DATABASE suadin;
,CREATE USER suadin WITH PASSWORD 'jw8s0F4';
,GRANT CREATE ON DATABASE suadin TO suadin;
,\q
,exit
,exit
- use root user and follow guide for install pgAdmin4, scroll a bit down [source]
- change apache port to have no conflict with suadin.de [source]
- start pgAdmin4:
sudo /usr/pgadmin4/bin/setup-web.sh
- create subdomain https://db.suadin.de with external detour http://81.169.247.92:8080/pgadmin4
- follow certbot guide until step 6, use on step 7 webroot with domain suadin.de [source]
- stop deployment script,
sudo certbot certonly --standalone
with domain suadin.de- result:
/etc/letsencrypt/live/suadin.de/fullchain.pem
&/etc/letsencrypt/live/suadin.de/privkey.pem
- result:
- convert
privkey.pem
withfullchain.pem
tosuadin.de.pfx
, choose password [source] - prepare *.pfx for docker:
sudo cp suadin.de.pfx /home/docker/.aspnet/https/
(create missing folder) [source]
- stop website with deployment script
su docker pkill screen container_id=$(docker ps -aqf "name=$repo" -aqf "status=running") if [ ! -z "$container_id" ]; then docker container stop "$container_id" fi
sudo certbot renew
- execute last two steps from Create-Certificate
- start deployment scrip
su docker cd ~ screen ./continuous-deployment.sh
- follow step 9 of certobot guide [source]
pre/haproxy.sh
contains first scriptblock from Renew-Manual-Certificatesudo certbot renew
is executed automatically between pre and postpost/haproxy.sh
contains- execute last two steps from Create-Certificate
- last scriptblock from Renew-Manual-Certificate
⚠️ But never did it, therefore open task to do setup.
Continuous Integration (CI) and Continuous Delivery (CD) of website happens through GitHub and DockerHub. Pull of docker image happens with deployment script on Server.
GitHub account suadin contains GIT repository of website.
- connect to GitHub repository source, choose main branch and link to existing Dockerfile
- expect push into GitHub triggers DockerHub build run
⚠️ If you get error 'COPY failed: stat /var/lib/docker/tmp/docker-builder...': I solved it by remove repo from docker-hub and create new with same name.
⚠️ DockerHub force you to Upgrade your account if you need a connection to github: Solved that by using GitHub Actions to push images to DockerHub.
- put DockerHub secrets into GitHub [source]
- follow guide to push docker image into DockerHub & GitHub Packages [source]
- do slidely changes on last step [source]
- add on both
build & publish
steps below contextfile: src/Server/Dockerfile
- replace hashed versions
docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with major versionsdocker/build-push-action@v2
- add on both
ℹ️ Change to GitHub Packages to remove DockerHub dependency
#!/bin/bash
repo="<repo-name>"
feed="<dockerhub-id>/$repo:main"
docker_params="-p 80:80 -p 443:443 -e ASPNETCORE_URLS=\"https://+443;http://+80\" -e ASPNETCORE_HTTPS_PORT=443 -e ASPNETCORE_Kestrel__Certificates__Default__Password=\"$cert_password\" -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/suadin.de.pfx -v ~/.aspnet/https:/https/"
while [ true ]
do
sleep 1
docker container prune -f
docker image prune -a -f
sleep 1
container_id=$(docker ps -aqf "name=$repo" -aqf "status=running")
pull=$(docker pull $feed)
if [[ $pull == *"Status: Image is up to date for $feed"* ]]; then
if [ ! -z "$container_id" ]; then
echo "Nothing to do..."
else
# duplicated code, see below. For now ok but potential improvement exists.
echo "start container with image $feed"
screen -d -m bash -c "docker run $docker_params --name $repo $feed"
fi
sleep 60
elif [[ $pull == *"Downloaded newer image for $feed"* ]]; then
echo "New version detected!"
if [ ! -z "$container_id" ]; then
echo "stop container $container_id"
docker container stop "$container_id"
sleep 1
docker container prune -f
docker image prune -a -f
sleep 1
fi
echo "start container with image $feed"
secrets="--env-file secrets.txt"
screen -d -m bash -c "docker run $docker_params $secrets --name $repo $feed"
sleep 60
else
echo "Script doesn't work like expected, please verify!"
sleep 5
fi
done
Comments:
while [ true ]
&sleep 60
: minutely endless loopsleep 1
before/after prune necessary to avoid error messagescontainer_id=$(docker ps -aqf "name=$repo" -aqf "status=running")
: take container id for potential stop and prunepull=$(docker pull $feed)
: pull spam to detect potential changesdocker_params="-p 80:80 -p 443:443 ...
: configure ports, specially https with certificate binding [details]secrets="--env-file secrets.txt"
: for pass secrets into website [source]
Run:
- Start script manually:
screen ./continuous-deployment.sh
- Start after server reboot with CRON job:
nano /etc/crontab
-> add@reboot docker /usr/bin/screen -dmS continuous-deployment-screen /home/docker/continuous-deployment.sh