Compare commits
26 Commits
main
...
b6f55f1186
Author | SHA1 | Date | |
---|---|---|---|
b6f55f1186 | |||
8fe1bebb4b | |||
f803c5c74b | |||
df19e70c88 | |||
c273781043 | |||
ac4bad6936 | |||
83ec1528ca | |||
2f86815728 | |||
349e64b54e | |||
e6e5b55f65 | |||
cbbc6f3ae4 | |||
8ba4e824fc | |||
cc7cb56aa3 | |||
2eca300dd0 | |||
48742d8a6f | |||
18d2f05e28 | |||
5e13584e7c | |||
ba86f05f5e | |||
03ebc12ac3 | |||
91445e4c60 | |||
bfad48fff1 | |||
f32cc1b6a0 | |||
589b269ae3 | |||
a2811c81ad | |||
aa6fa836ae | |||
d5a41badcf |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
gitea-data
|
||||
jenkins-data
|
||||
nginx
|
75
ansible/Jenkinsfile
vendored
Normal file
75
ansible/Jenkinsfile
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
ANSIBLE_HOST_KEY_CHECKING = 'false'
|
||||
VAULT_PASSWORD = credentials('vault_password')
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(name: 'ADDITIONAL_CONTENT_SITEA_H2', defaultValue: 'Новое сообщение для SiteA', description: 'Additional <h2> content for SiteA')
|
||||
string(name: 'ADDITIONAL_CONTENT_SITEA_P', defaultValue: 'Дополнительный параграф для SiteA', description: 'Additional <p> content for SiteA')
|
||||
string(name: 'ADDITIONAL_CONTENT_SITEB_H2', defaultValue: 'Новое сообщение для SiteB', description: 'Additional <h2> content for SiteB')
|
||||
string(name: 'ADDITIONAL_CONTENT_SITEB_P', defaultValue: 'Дополнительный параграф для SiteB', description: 'Additional <p> content for SiteB')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Decrypt SSH Key') {
|
||||
steps {
|
||||
script {
|
||||
def tempDir = '/tmp/' + UUID.randomUUID().toString()
|
||||
env.TEMP_DIR = tempDir
|
||||
sh "mkdir -p ${tempDir}"
|
||||
|
||||
def decryptedKeyFile = "${tempDir}/id_ed25519"
|
||||
def vaultPassFile = "${tempDir}/vault_pass"
|
||||
|
||||
writeFile file: vaultPassFile, text: VAULT_PASSWORD
|
||||
|
||||
sh """
|
||||
ansible-vault decrypt ./ansible/id_ed25519_vault --output=${decryptedKeyFile} --vault-password-file=${vaultPassFile}
|
||||
"""
|
||||
|
||||
env.DECYPTED_KEY_FILE = decryptedKeyFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy Site') {
|
||||
steps {
|
||||
script {
|
||||
def extraVars = [
|
||||
siteA_h2: params.ADDITIONAL_CONTENT_SITEA_H2,
|
||||
siteA_p: params.ADDITIONAL_CONTENT_SITEA_P,
|
||||
siteB_h2: params.ADDITIONAL_CONTENT_SITEB_H2,
|
||||
siteB_p: params.ADDITIONAL_CONTENT_SITEB_P,
|
||||
ansible_ssh_private_key_file: env.DECYPTED_KEY_FILE
|
||||
]
|
||||
|
||||
ansiblePlaybook(
|
||||
playbook: 'ansible/playbook.yml',
|
||||
inventory: "ansible/inventory.yml",
|
||||
extraVars: extraVars,
|
||||
limit: 'SiteA,SiteB,proxy'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
if (env.TEMP_DIR) {
|
||||
sh "rm -rf ${env.TEMP_DIR}"
|
||||
}
|
||||
}
|
||||
}
|
||||
success {
|
||||
echo 'Deployment completed successfully.'
|
||||
}
|
||||
failure {
|
||||
echo 'Deployment failed. Please check the logs for more details.'
|
||||
}
|
||||
}
|
||||
}
|
4
ansible/ansible.cfg
Normal file
4
ansible/ansible.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
[defaults]
|
||||
inventory = inventory.yml
|
||||
roles_path = ./roles
|
||||
host_key_checking = False
|
19
ansible/group_vars/all.yml
Normal file
19
ansible/group_vars/all.yml
Normal file
@ -0,0 +1,19 @@
|
||||
siteA:
|
||||
site_title: "SiteA - Добро пожаловать"
|
||||
site_h1: "Добро пожаловать на SiteA"
|
||||
site_h2: "{{ siteA_h2 }}"
|
||||
site_p: "{{ siteA_p }}"
|
||||
site_domain: "siteA.example.com"
|
||||
site_ip: "192.168.0.61"
|
||||
|
||||
siteB:
|
||||
site_title: "SiteB - Добро пожаловать"
|
||||
site_h1: "Добро пожаловать на SiteB"
|
||||
site_h2: "{{ siteB_h2 }}"
|
||||
site_p: "{{ siteB_p }}"
|
||||
site_domain: "siteB.example.com"
|
||||
site_ip: "192.168.0.62"
|
||||
|
||||
proxy:
|
||||
proxy_domain: "proxy.example.com"
|
||||
proxy_ip: "192.168.0.63"
|
26
ansible/id_ed25519_vault
Normal file
26
ansible/id_ed25519_vault
Normal file
@ -0,0 +1,26 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
63306262646434323632386463373239336566633737636235653430333132386537366564666234
|
||||
6461393163343265306366313736313961373630313234340a323534616566666137616431386461
|
||||
65373333643664633833613431666531353935646562396661623163343464663262396264643537
|
||||
6261363038363062640a616431336162386465316639376662333066396535623735383032316538
|
||||
36613839386139363661636536306361373231623432663331623766346262366230353432373538
|
||||
34353032303461323533396438306561386332396266316565393930653038623361333163323736
|
||||
63663734333034336337373632333565333633306361633335663365336161636439386563393736
|
||||
33613262623862626161653466626339623861353566323864363231343365333666326163396538
|
||||
30353265613330626261363038633762373531623864333937366361616465313961363536636430
|
||||
37333739333661303865376137343931363563656362316339383033326539343135663936393931
|
||||
36653363656535656334613264653932666231663930353931306662333833366534343365386136
|
||||
61336538356164653433613930343137373534653732613830366439343061313166656533323230
|
||||
65353938383563646162373232613632313332643765313135653730383864643539333732623739
|
||||
32393239373735616463633830333136616438316361613336613336613766356538313534303939
|
||||
64646262323164643336653761663338613036376365613565373561626366643765396564383665
|
||||
38303135356639373762303139633862313833313063373737633336363939336438376239613536
|
||||
65636539653335396464653363613339383862653862336630353364636162663237383163666134
|
||||
30643865383533623461303630356631396135663265376264663637326136663161656638616332
|
||||
32626636613138313232396636343032343666343039353533626131663235393235343966303662
|
||||
30336364363361356339303466633165316330376336306130336536656134336130376137613663
|
||||
34333136306638306332356363616165343536666239366532333630306535626532656438613030
|
||||
37626535316532623134633238313733353566373630333834616132353061656530373763303531
|
||||
33366536363333303966663663353865613532353164623762636531366535393465623239643765
|
||||
39626662633164623734626433313132633532336161363036633434393432393934396663633531
|
||||
6333
|
14
ansible/inventory.yml
Normal file
14
ansible/inventory.yml
Normal file
@ -0,0 +1,14 @@
|
||||
all:
|
||||
children:
|
||||
SiteA:
|
||||
hosts:
|
||||
192.168.0.61:
|
||||
ansible_user: ansible
|
||||
SiteB:
|
||||
hosts:
|
||||
192.168.0.62:
|
||||
ansible_user: ansible
|
||||
proxy:
|
||||
hosts:
|
||||
192.168.0.63:
|
||||
ansible_user: ansible
|
15
ansible/playbook.yml
Normal file
15
ansible/playbook.yml
Normal file
@ -0,0 +1,15 @@
|
||||
- hosts: all
|
||||
become: true
|
||||
roles:
|
||||
- firewall
|
||||
|
||||
- hosts: SiteA,SiteB
|
||||
become: true
|
||||
roles:
|
||||
- nginx_site
|
||||
|
||||
- hosts: proxy
|
||||
become: true
|
||||
roles:
|
||||
- ssl_certificate
|
||||
- nginx_proxy
|
18
ansible/roles/firewall/tasks/main.yml
Normal file
18
ansible/roles/firewall/tasks/main.yml
Normal file
@ -0,0 +1,18 @@
|
||||
- name: Install firewalld
|
||||
zypper:
|
||||
name: firewalld
|
||||
state: present
|
||||
|
||||
- name: Ensure firewalld is enabled and started
|
||||
systemd:
|
||||
name: firewalld
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Open specified firewall ports
|
||||
firewalld:
|
||||
port: "{{ item.port }}/{{ item.protocol }}"
|
||||
permanent: yes
|
||||
state: enabled
|
||||
immediate: yes
|
||||
loop: "{{ firewall_ports }}"
|
4
ansible/roles/firewall/vars/main.yml
Normal file
4
ansible/roles/firewall/vars/main.yml
Normal file
@ -0,0 +1,4 @@
|
||||
firewall_ports:
|
||||
- { port: 22, protocol: tcp }
|
||||
- { port: 80, protocol: tcp }
|
||||
- { port: 443, protocol: tcp }
|
20
ansible/roles/nginx_proxy/tasks/main.yml
Normal file
20
ansible/roles/nginx_proxy/tasks/main.yml
Normal file
@ -0,0 +1,20 @@
|
||||
- name: Install Nginx
|
||||
zypper:
|
||||
name: nginx
|
||||
state: present
|
||||
|
||||
- name: Ensure Nginx is enabled and started
|
||||
systemd:
|
||||
name: nginx
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Deploy Proxy Configuration
|
||||
template:
|
||||
src: proxy.conf.j2
|
||||
dest: /etc/nginx/conf.d/proxy.conf
|
||||
|
||||
- name: Reload Nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
29
ansible/roles/nginx_proxy/templates/proxy.conf.j2
Normal file
29
ansible/roles/nginx_proxy/templates/proxy.conf.j2
Normal file
@ -0,0 +1,29 @@
|
||||
upstream backend {
|
||||
{% for server in upstream_servers %}
|
||||
server {{ server }} max_fails=3 fail_timeout=30s;
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl;
|
||||
server_name {{ proxy.proxy_domain }};
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/{{ ssl_cert_file }};
|
||||
ssl_certificate_key /etc/nginx/ssl/{{ ssl_key_file }};
|
||||
|
||||
location / {
|
||||
proxy_pass http://backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://backend/health;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
3
ansible/roles/nginx_proxy/vars/main.yml
Normal file
3
ansible/roles/nginx_proxy/vars/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
upstream_servers:
|
||||
- "{{ siteA.site_ip }}"
|
||||
- "{{ siteB.site_ip }}"
|
67
ansible/roles/nginx_site/tasks/main.yml
Normal file
67
ansible/roles/nginx_site/tasks/main.yml
Normal file
@ -0,0 +1,67 @@
|
||||
- name: Install Nginx
|
||||
zypper:
|
||||
name: nginx
|
||||
state: present
|
||||
|
||||
- name: Ensure Nginx is enabled and started
|
||||
systemd:
|
||||
name: nginx
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Create web root for SiteA
|
||||
file:
|
||||
path: /var/www/siteA
|
||||
state: directory
|
||||
owner: nginx
|
||||
group: nginx
|
||||
mode: '0755'
|
||||
when: inventory_hostname in groups['SiteA']
|
||||
|
||||
- name: Create web root for SiteB
|
||||
file:
|
||||
path: /var/www/siteB
|
||||
state: directory
|
||||
owner: nginx
|
||||
group: nginx
|
||||
mode: '0755'
|
||||
when: inventory_hostname in groups['SiteB']
|
||||
|
||||
- name: Deploy SiteA Configuration
|
||||
template:
|
||||
src: siteA.conf.j2
|
||||
dest: /etc/nginx/conf.d/siteA.conf
|
||||
when: inventory_hostname in groups['SiteA']
|
||||
|
||||
- name: Deploy SiteB Configuration
|
||||
template:
|
||||
src: siteB.conf.j2
|
||||
dest: /etc/nginx/conf.d/siteB.conf
|
||||
when: inventory_hostname in groups['SiteB']
|
||||
|
||||
- name: Deploy SiteA HTML
|
||||
template:
|
||||
src: index.html.j2
|
||||
dest: /var/www/siteA/index.html
|
||||
vars:
|
||||
site_title: "{{ siteA.site_title }}"
|
||||
site_h1: "{{ siteA.site_h1 }}"
|
||||
site_h2: "{{ siteA.site_h2 }}"
|
||||
site_p: "{{ siteA.site_p }}"
|
||||
when: inventory_hostname in groups['SiteA']
|
||||
|
||||
- name: Deploy SiteB HTML
|
||||
template:
|
||||
src: index.html.j2
|
||||
dest: /var/www/siteB/index.html
|
||||
vars:
|
||||
site_title: "{{ siteB.site_title }}"
|
||||
site_h1: "{{ siteB.site_h1 }}"
|
||||
site_h2: "{{ siteB.site_h2 }}"
|
||||
site_p: "{{ siteB.site_p }}"
|
||||
when: inventory_hostname in groups['SiteB']
|
||||
|
||||
- name: Reload Nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
24
ansible/roles/nginx_site/templates/index.html.j2
Normal file
24
ansible/roles/nginx_site/templates/index.html.j2
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ site_title }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
padding-top: 50px;
|
||||
}
|
||||
h1 { color: #ff5722; }
|
||||
h2 { color: #ff9800; }
|
||||
p { font-size: 18px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ site_h1 }}</h1>
|
||||
<h2>{{ site_h2 }}</h2>
|
||||
<p>{{ site_p }}</p>
|
||||
</body>
|
||||
</html>
|
16
ansible/roles/nginx_site/templates/siteA.conf.j2
Normal file
16
ansible/roles/nginx_site/templates/siteA.conf.j2
Normal file
@ -0,0 +1,16 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ siteA.site_domain }};
|
||||
|
||||
root /var/www/siteA;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
location /health {
|
||||
return 200 'SiteA is up';
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
16
ansible/roles/nginx_site/templates/siteB.conf.j2
Normal file
16
ansible/roles/nginx_site/templates/siteB.conf.j2
Normal file
@ -0,0 +1,16 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ siteB.site_domain }};
|
||||
|
||||
root /var/www/siteB;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
location /health {
|
||||
return 200 'SiteB is up';
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
1
ansible/roles/nginx_site/vars/main.yml
Normal file
1
ansible/roles/nginx_site/vars/main.yml
Normal file
@ -0,0 +1 @@
|
||||
additional_content: "{{ additional_content | default('') }}"
|
22
ansible/roles/ssl_certificate/tasks/main.yml
Normal file
22
ansible/roles/ssl_certificate/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
||||
- name: Install OpenSSL
|
||||
zypper:
|
||||
name: openssl
|
||||
state: present
|
||||
|
||||
- name: Create SSL directory
|
||||
file:
|
||||
path: "{{ ssl_cert_path }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Generate Self-Signed SSL Certificate
|
||||
command: >
|
||||
openssl req -x509 -nodes -days 365
|
||||
-newkey rsa:2048
|
||||
-keyout {{ ssl_cert_path }}/{{ ssl_key_file }}
|
||||
-out {{ ssl_cert_path }}/{{ ssl_cert_file }}
|
||||
-subj "{{ ssl_subject }}"
|
||||
args:
|
||||
creates: "{{ ssl_cert_path }}/{{ ssl_cert_file }}"
|
4
ansible/roles/ssl_certificate/vars/main.yml
Normal file
4
ansible/roles/ssl_certificate/vars/main.yml
Normal file
@ -0,0 +1,4 @@
|
||||
ssl_cert_path: "/etc/nginx/ssl"
|
||||
ssl_cert_file: "proxy.crt"
|
||||
ssl_key_file: "proxy.key"
|
||||
ssl_subject: "/C=RU/ST=Some-State/L=Some-City/O=Your Company/CN={{ proxy.proxy_domain }}"
|
0
ansible/roles/vars/main.yml
Normal file
0
ansible/roles/vars/main.yml
Normal file
31
docker-compose.yml
Normal file
31
docker-compose.yml
Normal file
@ -0,0 +1,31 @@
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
container_name: nginx
|
||||
volumes:
|
||||
- ./nginx/conf.d:/etc/nginx/conf.d
|
||||
- ./nginx/ssl:/etc/nginx/ssl
|
||||
- ./nginx/html:/usr/share/nginx/html
|
||||
- /coursework/nginx/ssl:/coursework/nginx/ssl
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
depends_on:
|
||||
- gitea
|
||||
restart: always
|
||||
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
volumes:
|
||||
- ./gitea-data:/data
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "222:22"
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
gitea-data:
|
Reference in New Issue
Block a user