29 Commits
Author SHA1 Message Date
emil28092005 bfe848f335 Tryiing to fix Jenkins. 2026-01-18 05:23:17 +03:00
emil28092005 cce78fa8b3 Try fixing Jenkins. 2026-01-18 01:48:00 +00:00
emil28092005 e67fb2ffe2 Try fixing Jenkins. 2026-01-18 01:47:32 +00:00
emil28092005 98f505ce88 Try fixing Jenkins. 2026-01-18 01:46:29 +00:00
emil28092005 da850e6086 Try fixing Jenkins. 2026-01-18 01:42:20 +00:00
emil28092005 4aa6aad6cb Try fixing Jenkins. 2026-01-18 01:07:38 +00:00
emil28092005 eb476c0b9d Try fixing Jenkins. 2026-01-18 01:03:36 +00:00
emil28092005 dab959d1a5 Try fixing Jenkins. 2026-01-18 01:00:20 +00:00
emil28092005 3929678a43 Try fixing Jenkins. 2026-01-18 00:58:13 +00:00
emil28092005 ce46878054 Try fixing Jenkins. 2026-01-17 22:40:55 +00:00
emil28092005 1e29b2e624 Try fixing Jenkins. 2026-01-17 22:28:22 +00:00
emil28092005 d2b12d2e5a Try fixing Jenkins. 2026-01-17 22:25:36 +00:00
emil28092005 c25952bbc1 Try fixing Jenkins 2026-01-16 23:52:50 +03:00
emil28092005 5b8f9bc1ab Try fixing Jenkins 2026-01-16 23:23:09 +03:00
emil28092005 04d0e2ae31 remake architecture. 2026-01-16 23:17:44 +03:00
emil28092005 4259295ba3 Try fixing Jenkins. 2026-01-16 21:26:28 +03:00
emil28092005 b98326f510 Try fixing Jenkins. 2026-01-16 21:17:13 +03:00
emil28092005 7db2a78c0b Try fixing Jenkins. 2026-01-16 21:08:46 +03:00
emil28092005 cbc6ff04f6 Try fixing Jenkins. 2026-01-16 21:02:33 +03:00
emil28092005 c7955ecee7 Fix WebSocket connection. 2026-01-16 20:31:39 +03:00
emil28092005 acede2104a Fix docker-compose-jenkins.yml 2026-01-16 08:50:53 +03:00
emil28092005 5895990cbb Fix Jenkinsfile. 2026-01-16 08:26:11 +03:00
emil28092005 320d4d7502 Fix Jenkinsfile. 2026-01-16 08:10:07 +03:00
emil28092005 cc70057b63 Fix Jenkinsfile. 2026-01-16 08:02:26 +03:00
emil28092005 dbe3b79fb5 Fix Jenkinsfile. 2026-01-16 07:49:05 +03:00
emil28092005 0e56d9f1f8 Add Jenkinsfile. 2026-01-16 07:42:19 +03:00
emil28092005 b894e3a6f1 docker-compose-jenkins.yml 2026-01-16 07:17:56 +03:00
emil28092005 19433276af docker-compose-jenkins.yml + minor fixes. 2026-01-16 07:14:11 +03:00
Emil Shanaty 552fc6b9a8 Merge pull request #4 from emil28092005/dev
Dev
2026-01-14 04:58:57 +03:00
15 changed files with 264 additions and 89 deletions
+3 -1
View File
@@ -1,2 +1,4 @@
project_context.txt project_context.txt
shagram.db shagram.db
deploy/shagram/nginx/certs/*.pem
deploy/shagram/.env
+10 -8
View File
@@ -1,20 +1,22 @@
FROM golang:1.25.5-alpine AS builder FROM golang:1.25.5-alpine AS builder
RUN apk add --no-cache build-base ca-certificates
RUN apk add --no-cache build-base
WORKDIR /app WORKDIR /app
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN --mount=type=cache,target=/go/pkg/mod \
go mod download
COPY . . COPY . .
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o shagram ./cmd/server RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=1 GOOS=linux go build -o shagram ./cmd/server
FROM alpine:latest FROM alpine:latest
RUN apk --no-cache add ca-certificates sqlite-libs RUN apk add --no-cache ca-certificates sqlite-libs sqlite
WORKDIR /app WORKDIR /app
COPY --from=builder /app/shagram . COPY --from=builder /app/shagram .
COPY static ./static COPY static ./static
COPY migrations ./migrations COPY migrations ./migrations
RUN mkdir -p /app/data RUN mkdir -p /app/data
EXPOSE 8080 EXPOSE 8080
CMD ["./shagram"] CMD ["./shagram"]
Vendored
+67
View File
@@ -0,0 +1,67 @@
pipeline {
agent { label 'docker-agent' }
options {
skipDefaultCheckout(true)
timestamps()
}
environment {
IMAGE_NAME = "shagram"
DEPLOY_DIR = "/opt/shagram/shagram/deploy/shagram"
COMPOSE_FILE = "${WORKSPACE}/deploy/shagram/compose.yaml"
}
stages {
stage('Checkout') {
steps {
checkout scm
sh '''
set -eux
git reset --hard
git clean -xffd
'''
}
}
stage('Build') {
steps {
script {
env.GIT_SHA = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
env.APP_IMAGE = "${IMAGE_NAME}:${env.GIT_SHA}"
}
sh '''
set -eux
docker build -t "$APP_IMAGE" .
'''
}
}
stage('Test') {
steps {
sh '''
echo "Testing..."
'''
}
}
stage('Deploy') {
when {
beforeAgent true
branch 'main'
}
steps {
sh '''
set -eux
mkdir -p "$DEPLOY_DIR"
cat > "$DEPLOY_DIR/.env" <<EOF
APP_IMAGE=$APP_IMAGE
EOF
docker compose -f "$COMPOSE_FILE" --project-directory "$DEPLOY_DIR" up -d --remove-orphans
'''
}
}
}
}
View File
+6 -1
View File
@@ -3,6 +3,7 @@ package main
import ( import (
"log" "log"
"net/http" "net/http"
"os"
"shagram/internal/api" "shagram/internal/api"
"shagram/internal/db" "shagram/internal/db"
"shagram/internal/models" "shagram/internal/models"
@@ -12,7 +13,11 @@ import (
) )
func main() { func main() {
database, err := db.NewDB("/app/data/shagram.db") dbPath := os.Getenv("DATABASE_PATH")
if dbPath == "" {
dbPath = "/app/data/shagram.db"
}
database, err := db.NewDB(dbPath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
+26
View File
@@ -0,0 +1,26 @@
services:
shagram:
image: ${APP_IMAGE:-shagram:local}
build:
context: ../..
container_name: shagram-app
environment:
- DATABASE_PATH=/app/data/shagram.db
volumes:
- shagram_data:/app/data
expose:
- "8080"
nginx:
image: nginx:alpine
container_name: shagram-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/certs:/etc/nginx/certs:ro
depends_on:
- shagram
volumes:
shagram_data:
View File
+34
View File
@@ -0,0 +1,34 @@
# TLS Certificates for Nginx (Development / Self-Signed)
In production, TLS certificates are typically issued by a trusted Certificate Authority (for example, via Lets Encrypt).
For local development and demo environments, a self-signed certificate can be used.
## Generate a self-signed certificate (Linux/macOS)
From the repository root:
```bash
mkdir -p deploy/shagram/nginx/certs
openssl req -x509 -newkey rsa:4096 \
-keyout deploy/shagram/nginx/certs/key.pem \
-out deploy/shagram/nginx/certs/cert.pem \
-sha256 -days 365 -nodes \
-subj "/C=RU/ST=Moscow/L=Korolyov/O=Shagram/CN=localhost"
```
## Verify
```bash
openssl x509 -in deploy/shagram/nginx/certs/cert.pem -noout -text | head
```
## Usage
The Nginx configuration expects:
- `deploy/shagram/nginx/certs/cert.pem`
- `deploy/shagram/nginx/certs/key.pem`
Start the deployment:
```bash
cd deploy/shagram
docker compose up -d
```
-26
View File
@@ -1,26 +0,0 @@
version: '3.8'
services:
shagram:
build: .
ports:
- "8080"
volumes:
- ./data:/app/data
- ./static:/app/static
- ./migrations:/app/migrations
environment:
- DATABASE_PATH=/app/shagram.db
container_name: shagram-app
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
- ./nginx/certs:/etc/nginx/certs
depends_on:
- shagram
container_name: shagram-nginx
+78
View File
@@ -0,0 +1,78 @@
# Jenkins (Controller + Docker Agent) Setup (Docker Compose)
This directory contains a minimal Jenkins setup using a dedicated **controller** and a separate inbound **agent** intended for Docker-based workloads.
The goal is to keep the controller responsible for orchestration and configuration, while all builds run on the agent labeled `docker`.
## Prerequisites
- Docker Engine installed on the host
- Docker Compose available as `docker compose`
- A host directory `/opt/shagram` (used by pipelines as a shared location for source code and deployment files)
## Start Jenkins
From the repository root:
```bash
cd infra/jenkins
docker compose up -d
docker compose ps
```
Jenkins UI will be available at:
- http://<server-ip>:8080
### Initial admin password
Retrieve the initial password with:
```bash
docker exec -it jenkins-controller cat /var/jenkins_home/secrets/initialAdminPassword
```
## Disable builds on the built-in node (Executors = 0)
To ensure builds do not run on the controller:
1. Open Jenkins UI
2. Go to: **Manage Jenkins → Manage Nodes and Clouds**
3. Open **Built-In Node → Configure**
4. Set **Number of executors** to `0`
5. Save
## Create an inbound agent node (docker-agent)
Create a dedicated node for running pipelines:
1. Go to: **Manage Jenkins → Manage Nodes and Clouds → New Node**
2. Set:
- **Node name**: `docker-agent`
- **Type**: Permanent Agent
- **Remote root directory**: `/home/jenkins/agent`
- **Labels**: `docker`
- **Usage**: Only build jobs with label expressions matching this node
3. Save
After saving, open the agent page:
- **Manage Nodes and Clouds → docker-agent**
On that page, Jenkins provides the inbound connection details, including the **secret** required by the inbound agent container.
## Configure the agent secret in Compose
Edit `infra/jenkins/compose.yaml` and replace:
- `JENKINS_SECRET=__PASTE_ME__`
with the real secret value shown on the `docker-agent` node page.
Restart only the agent container:
```bash
docker compose up -d --force-recreate jenkins-agent-docker
docker logs -f jenkins-agent-docker
```
## Verification
- In Jenkins UI: **Manage Nodes and Clouds**, the node `docker-agent` should be **Online**
- Any pipeline using `agent { label 'docker' }` should execute on this agent
## Security note
The Docker agent container mounts `/var/run/docker.sock`, which effectively grants high-level control over the Docker host. Use this setup only in trusted environments and limit access to Jenkins accordingly.
+37
View File
@@ -0,0 +1,37 @@
services:
jenkins-controller:
image: jenkins/jenkins:lts-jdk17
container_name: jenkins-controller
ports:
- "8080:8080"
volumes:
- jenkins_home:/var/jenkins_home
restart: unless-stopped
jenkins-agent-docker:
image: jenkins/inbound-agent:latest-jdk17
container_name: jenkins-agent-docker
user: "1000:1000"
group_add:
- "988"
environment:
- JENKINS_URL=http://jenkins-controller:8080
- JENKINS_AGENT_NAME=docker-agent
- JENKINS_SECRET=0c92dc0b807b3c7213cd2abcec4f88182aa8f4fb2233ca9c674f17fd771fe662
- AGENT_WORKDIR=/home/jenkins/agent
volumes:
- agent_workdir:/home/jenkins/agent
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
- /usr/libexec/docker/cli-plugins:/usr/libexec/docker/cli-plugins:ro
- /opt/shagram:/opt/shagram
restart: unless-stopped
depends_on:
- jenkins-controller
volumes:
jenkins_home:
external: true
name: jenkins_jenkins_home
agent_workdir:
-22
View File
@@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDjzCCAnegAwIBAgIUG1Qc10mXTy5+Zuh1COAK6fqAl34wDQYJKoZIhvcNAQEL
BQAwVzELMAkGA1UEBhMCUlUxDzANBgNVBAgMBk1vc2NvdzERMA8GA1UEBwwIS29y
b2x5b3YxEDAOBgNVBAoMB1NoYWdyYW0xEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0y
NjAxMTQwMTMxNDhaFw0yNzAxMTQwMTMxNDhaMFcxCzAJBgNVBAYTAlJVMQ8wDQYD
VQQIDAZNb3Njb3cxETAPBgNVBAcMCEtvcm9seW92MRAwDgYDVQQKDAdTaGFncmFt
MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDLOB4WybryG6Cc4yU+2PPrLiM/tt15HMVp0TgcA277vofYFd90IArihbmG
KEaKYyZplUzxk55RRNS6BaAroZb0AWEg8cOid83gbnuKKaIUhjz/CDADPnnRWynb
PHjVuvIBtPLgyunbtB6U7a6JLP2nA8XaTcDFtLrhy8PTKFZ9fLRBXzxW8ZvNnL4i
FSLQYe851dOfJ1m0HwA/meK8QWfYn01O8zprleSMo+HPIudRR6ySnx/Cy3LuAcqM
sjttf6EFWs9XTiAOIbKC4M8VbOrfZjXFz45ljD0tZNziJ2g61lmdJAV8ElwZ6SDP
fGTwGjWj5Qx9Lg7qdFqjVyE0QFBJAgMBAAGjUzBRMB0GA1UdDgQWBBSd7S5Xngb4
9eeBbmTCslblkWClRDAfBgNVHSMEGDAWgBSd7S5Xngb49eeBbmTCslblkWClRDAP
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA8Lx0PAhfYRuRYuQxV
EyU4pmQ6JuAPl3gxVKHY6bFGMYooSRr5Nw/YulfPucxTKHtVlgY/l0kwofmTUh3B
Df1tulFCCmBW4zbl6cHd7TVSEJBkV7R9AqAC49ni8mVhmo3uPuARFa+mR8ATrF4y
LWlO/2n7F5g+093CqOG3b4O76PlqAl6L/z/Z+UBoMVEyiPgfxAztucsBn7oOaQwG
g6ohX2kosC2uRsc1bAofHWW0u3tFY0i6oiI7XPF9REuWJOiDlN2PsDMXhSG5xeLj
e7LUOQsNXB5deAfUFxbtEDCnEDzyp+GxXwZ0iPsJOzm2ccL6XdDzucCuR/NtuhGf
KwpD
-----END CERTIFICATE-----
-28
View File
@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLOB4WybryG6Cc
4yU+2PPrLiM/tt15HMVp0TgcA277vofYFd90IArihbmGKEaKYyZplUzxk55RRNS6
BaAroZb0AWEg8cOid83gbnuKKaIUhjz/CDADPnnRWynbPHjVuvIBtPLgyunbtB6U
7a6JLP2nA8XaTcDFtLrhy8PTKFZ9fLRBXzxW8ZvNnL4iFSLQYe851dOfJ1m0HwA/
meK8QWfYn01O8zprleSMo+HPIudRR6ySnx/Cy3LuAcqMsjttf6EFWs9XTiAOIbKC
4M8VbOrfZjXFz45ljD0tZNziJ2g61lmdJAV8ElwZ6SDPfGTwGjWj5Qx9Lg7qdFqj
VyE0QFBJAgMBAAECggEALgf0UtOXd6M35omSBHIWkBknjVVRxc71TYKBS+EgOMA/
23ua3Z4rcQN60k9ZqRuL1iMmJls6Y2yspcVD8lYcEAGm+1Qf7PNnrBRCgflrt+vv
MZJsc7OpWrlkWf9Q3JLHogjXcgEsZyJdwfyzielpvDS/0nLFvVKyeRZTcUdEDhCz
MoY3tqcZVwq1k+CsW5Z8C1DZaEwgwhEXNGPgfX7R86FSNwlNmcTKJG/YHb9xBA84
O109pfe9PsQnYB9Lw+CNPHl1v6wIMRlVZZMFPevBJq+r9d8iN6dsX7c4oR8SXDDS
4Shux9RNE8XyD6HOTK+QuEvJmZmPIFjnlVZIsVkpHQKBgQD5bfeh7En+VPdHFGTg
+0o1ZSYrfvErak8zP7DoLZF4EY6CK20uZ8ou09ebWXZQfC37PliOSMJyDG70PuXc
Rh/TfnUPkPbmyRrvQi+MAsIjCEYGk2iiMQvSVs099AB6oAQetyPm2AcT4HeGNaLM
m1gurXTCelV0yT7oL7IhI6AqRQKBgQDQkoenTQ1nnvA4ghN253c+mbJWvTX+lbo9
WicOAxmA9gp/VN7NErXbgr5FcMwPtT+yLDqDgSjLp2T9ClYt/laWcO/KYwrnP9o5
DTeSB+biEAd3GHJLWJApY/dmFZey5uza+hXvlTdVCUgvFJYGgHw/Dg5E+jvUwrNT
MNN/OnpQNQKBgAtxxz3vuIlp3pqtTd+gyAvhIzo1rd0fGJkyX+yXQqhurco9MdpC
Ot2hLLBdD3er6vQvLSMCJaHT/jdIt4U+1nD+yWI4dYurSIgX0lSrP7sZwxTEKLXg
aDlzcCFak7cMpoO+RXBvEwwPbYyD439d1VL29HeD423jWfaPUa4Bk3S9AoGAWGdj
PBQ6tEr3wtvPaDyfnFcE8iLsueW4tLx7hULnEnQ26tWMQhvGHS6De2dd9uJ6Bwkc
HBUot3lSIra45HHDPazM1lm4i1/THQ9vGGRlBjiJEX+5Ihp9sC2A9TH9xISArCgI
GC6E73QptlrhZAwdnZRVlAMETR/hZkdxvaGJqmkCgYEAzHpqhLMFwOOvDr5Ya2DW
5IGSCohsNBRvPKLSXlMIT1yMfRStsp5qQrZq2Oj2xXX7Jk3jf+1lU3ZQ5O6bI6br
9MhrVKu6qI8YS3OtSDPAUOzPw1zu4yaKyCO0eNghY51PTZd3A3JA8Uh9Si7OCryD
iHnkhUQ1iasZLdnubyVUuh0=
-----END PRIVATE KEY-----
+3 -3
View File
@@ -23,12 +23,12 @@ function loadRooms() {
function connectRoom() { function connectRoom() {
const room = roomSelect.value || 'general'; const room = roomSelect.value || 'general';
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const host = window.location.host;
if (ws) { if (ws) {
ws.close(); ws.close();
} }
const wsUrl = `${protocol}//${host}/ws/${room}`;
ws = new WebSocket(`${protocol}//localhost:8080/ws/${room}`); ws = new WebSocket(wsUrl);