System administration - Seljaki/wiki GitHub Wiki

Uvod

V sklopu predmeta Sistemska administracija smo pridobili praktične izkušnje na področju upravljanja in vzdrževanja računalniških sistemov. Osredotočili smo se na ključne naloge, ki jih sistemski administratorji redno opravljajo, s posebnim poudarkom na Linux okolju. Naš cilj je bil vzpostaviti robustno in varno strežniško infrastrukturo, ki omogoča učinkovito in zanesljivo delovanje aplikacij.

Načrtovane naloge

Za vzpostavitev projekta smo uporabili:

  • Linux server
  • Docker
  • Docker hub
  • Github & github actions
  • Watchtower
  • Portainer
  • OpenVPN

Za naš projekt smo potrebovali strežnik, za dve spletni aplikaciji in podatkovno bazo. Odločili smo se za lasten strežnik, ker smo ga že imeli pripravljenega in konfiguriranega, ter tudi ker ima na voljo več pomnilnika od brezplačnega študentskega načrta, ki ga ponuja Microsoft Azure [1]. Strežnik ima 16gb pomnilnika, 6 jeder in nameščen distribucijo tipa Debian:

slika

Slika 1 : izpis programa neofetch na strežniku

Najprej sem ustvaril lokalni račun Mojci in Lovrotu in jima nato še omogočil dostop do strežnika preko VPN-a.

slika

Slika 2 : primer povezave vpn-a na strežnik

Za hitrejšo vzpostavitev dockerja, sem uporabil portainer [2], ki je spletna aplikacija za grafično upravljanje dockerja, ki nam je zelo ulajšala delo z dockerjem.

slika

Slika 3 : prikaz docker compose stacka v portainerju

Za upravljanje izvorne kode smo uporabili git in github, kjer smo meli avtomatske akcije (CI/CD), ki so se sprožle ob »merg-u« na main. Te akcije so posodobile sliko na docker hub-u, in sprožile posodobitev na strežniku.

slika

Slika 4 : prikaz server repozitorija na GitHub-u

slika

Slika 5 : prikaz uspešne akcije na GitHub-u

Slike smo nalagali na docker hub. Ker smo uporabljali brezplačen račun smo lahko imeli samo eno sliko privatno [3]. slika

Slika 6 : slika docker hub domače strani

Uporabili smo še WatchTower, za avtomatsko posodobitev slik. WatchTower je bil nameščen v dockerju. slika

Slika 7 : Prikaz poteka posodobitve slike na serverju

Implementacija

Github action

Ta GitHub Action konfiguracijska datoteka je zasnovana za avtomatizacijo procesa objavljanja Docker slike na Docker Hub vsakič, ko je koda potisnjena na glavno vejo (main) repozitorija.

Opis kode:

Za zagon akcij uporabimo ubuntu vm. Token je podan kot secret, za varno uporabo. Nato pridobimo podatke z repozatorija, nato zgradimo sliko z dockerfile-a, ki jo nato naložimo v docker hub. Potem počakamo okoli 30s, da poskrbimo da je docker slika naložena. Nato pošljemo http request z geslom na webhook servica watchtower, ki posodobi docker sliko na serveju.

name: Publish docker image

on:
push:
branches: ["main"]

jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:

- name: Check out the repo
uses: actions/checkout@v


- name: Log in to Docker Hub
uses: docker/login-action@v
with:
username: mrdog
password: ${{ secrets.DOCKER_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b
with:
images: mrdog210/seljaki-server
- name: Build and push Docker image
id: push
uses: docker/build-push-
action@3b5e8027fcad23fda98b2e3ac259d8d67585f
with:
context:.
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Waiting for docker upload
uses: jakejarvis/wait-action@master
with:
time: "30s"
- name: Webhook
uses: indiesdev/curl@v1.
with:
url: https://seljaki-watch.schnapsen66.eu/v1/update
method: "POST"
accept: 200,201,
timeout: 120000
bearer-token: ${{ secrets.WATCHTOWER_TOKEN }}
log-response: true
retries: 1

Dockerfile

Server

Koda je zelo preprosta, uporabimo najnovejši image node. Nastavimo delovni direktorij v sliki, prekopiramo datoteke, naložimo npm pakete in nastavimo začetni ukaz.

FROM node:latest

WORKDIR /server

COPY..


RUN npm install

CMD [ "npm", "run", "start" ]

Frontend

Ker se react buildati v html in js, potrebujemo dva imega. Najprej z builderom zgradimo sliko, kjer uporabimo podoben postopek kot pri serverju. Nato pa iz direktorija /build prekopiramo datoteke v http server image. Mi uporabljamo nginx so pa alternativi (apache).

Fetching the latest node image on apline linux

FROM node:alpine AS builder

# Declaring env
ENV NODE_ENV production
ENV REACT_APP_SERVER=https://seljaki-server.schnapsen66.eu

# Setting up the work directory
WORKDIR /app

# Installing dependencies
COPY ./package.json ./
RUN npm install

# Copying all the files in our project
COPY..

# Building our application
RUN npm run build

# Fetching the latest nginx image
FROM nginx

# Copying built assets from builder
COPY --from=builder /app/build /usr/share/nginx/html

# Copying our nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

Povezovanje na server

Ker odpiranje ssh porta javnosti ni zelo varno, saj je lahko ranljiv na ssh brute force napade, uporabljamo OpenVPN, kjer lahko dostopamo do vseh storitev strežnika, ki niso direktno odprte na splet, kot npr postgres strežnik ali grafični vmesnik za docker (portainer).

Avtomatsko posodabljanje docker slik na strežniku

Za avtomatsko posodabljanje slik uporabljamo program Watchtower [4]. Deluje tako, da ga dodamo v docker compose našega stacka in mu dodelimo direktorij od docker socketa in datoteke s podatki za prijavo na docker hub. Vsem slikam še dodamo ustrezen label, ki watchtower-ju pove katere slike naj nadzira za spremebo. Ko se zgodi sprememba slike, pošljemo request na webhook na protu 8081, kateremu priložimo geslo.

version: '3.8'

services:
  seljaki-frontend:
    image: mrdog210/seljaki-frontend:master
    restart: unless-stopped
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    environment:
      - REACT_APP_SERVER=https://seljaki-server.schnapsen66.eu
    ports:
      - 3332:80

  postgres_server:
    image: postgis/postgis:16-master
    restart: unless-stopped
    environment:
      POSTGRES_USER: seljaki
      POSTGRES_PASSWORD: alex18cm 
      POSTGRES_DB: seljaki
      POSTGRES_MULTIPLE_EXTENSIONS: postgis
    ports:
      - "5432:5432"
    volumes:
      # - ./sql-scripts:/docker-entrypoint-initdb.d
      - seljakidbpostgis:/var/lib/postgres
      
  seljaki-server:
    image: mrdog210/seljaki-server:main
    restart: unless-stopped
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    environment:
      - PORT=3000
      - PG_HOST=postgres_server
      - PG_PORT=5432
      - PG_DB=seljaki
      - PG_USERNAME=seljaki
      - PG_PASSWORD=alex18cm
      - JWT_SECRET=Shrek
    ports:
      - 3333:3000
    depends_on:
      - postgres_server
    
  watchtower:
    image: containrrr/watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.docker/config.json:/config.json
    command: --debug --http-api-update
    environment:
      - WATCHTOWER_HTTP_API_TOKEN=aaaa
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    ports:
      - 8081:8080

volumes: 
  seljakidbpostgis:

Avtomatski zagon testov

Ob novem merg requestu na main se zažene GH akcija, ki zažene teste in javi če so vsi uspešni. Test lahko zaženeš ročno, sprožijo pa se tudi avtomatsko.

name: Run tests

on:
  push:
    branches:
      - main
      - dev
  pull_request:
    branches:
      - main
      - dev
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repository code
        uses: actions/checkout@v2

      - name: Setup kotlin
        uses: gradle/actions/setup-gradle@v3

      - name: Make gradlew executable
        run: chmod +x ./gradlew && gradle wrapper

      - name: Build
        run: ./gradlew build

      - name: Run tests
        run: ./gradlew test

Nadgradnje projekta

Prihodnje nadgradnje, ki bi jih lahko uvedli, so samodejna gradna in objavljanje namizne aplikacije na github-u.

Zaključek

Skozi ta predmet smo si pridobili praktična znanja in veščine, ki so nujna za uspešno delovanje kot sistemski administratorji. Naš končni cilj je bil vzpostaviti stabilno, varno in učinkovito strežniško okolje, ki podpira avtomatizirane procese in omogoča zanesljivo delovanje aplikacij, na katero smo kar ponosni.

[1] „Azure for College Students—Offer Details | Microsoft Azure“. Pridobljeno: 31. maj 2024. [Na spletu]. Dostopno na: https://azure.microsoft.com/en-us/pricing/offers/ms-azr-0170p
[2] „Kubernetes and Docker Container Management Software“. Pridobljeno: 31. maj 2024. [Na spletu]. Dostopno na: https://www.portainer.io
[3] „Pricing | Docker“. Pridobljeno: 31. maj 2024. [Na spletu]. Dostopno na: https://www.docker.com/pricing/
[4] „containrrr/watchtower“. containrrr, 31. maj 2024. Pridobljeno: 31. maj 2024. [Na spletu]. Dostopno na: https://github.com/containrrr/watchtower