Restore from Gitea ZIP snapshot (12.08.2026) after full instance reinstall

Git history was lost when the previous Gitea instance was wiped and
reinstalled due to an unresolved corruption bug — this commit is the
last known-good file content, exported before the reinstall. Prior
commit history is not recoverable through this path.
This commit is contained in:
Claude Sonnet 5
2026-08-12 19:23:57 +00:00
commit 7320b8da8d
18 changed files with 483 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
*.retry
*.log
.env
*.swp
.DS_Store
__pycache__/
+9
View File
@@ -0,0 +1,9 @@
# osTicket Ansible Playbook for Debian 13
Автоматическая установка osTicket.
## Переменные для Semaphore
- `MARIADB_ROOT_PASSWORD` - пароль root MySQL
- `APP_DB_PASSWORD` - пароль пользователя osTicket
- `DOMAIN_NAME` - домен или IP сервера
+13
View File
@@ -0,0 +1,13 @@
---
- name: Полная установка osTicket с правильными правами
hosts: all
become: yes
gather_facts: yes
vars:
ansible_become_method: sudo
roles:
- apache
- php
- mariadb
- osticket
+33
View File
@@ -0,0 +1,33 @@
---
- name: Включение root доступа по SSH
hosts: all
become: yes
gather_facts: yes
tasks:
- name: Разрешить root логин через SSH
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin yes'
backup: yes
notify: Restart SSH
- name: Разрешить аутентификацию по паролю для root (если нужно)
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication yes'
notify: Restart SSH
- name: Убедиться, что SSH сервис запущен
ansible.builtin.systemd:
name: ssh
state: started
enabled: yes
handlers:
- name: Restart SSH
ansible.builtin.systemd:
name: ssh
state: restarted
+6
View File
@@ -0,0 +1,6 @@
# Переменные переопределяются в Semaphore через Environment Variables
mariadb_root_password: "{{ lookup('env', 'MARIADB_ROOT_PASSWORD') | default('CHANGE_ME', true) }}"
app_db_name: "osticket"
app_db_user: "osticket_user"
app_db_password: "{{ lookup('env', 'APP_DB_PASSWORD') | default('CHANGE_ME', true) }}"
domain_name: "{{ lookup('env', 'DOMAIN_NAME') | default('CHANGE_ME', true) }}"
+12
View File
@@ -0,0 +1,12 @@
---
- name: Полная установка osTicket
hosts: all
become: yes
become_method: sudo
gather_facts: yes
roles:
- apache
- php
- mariadb
- osticket
BIN
View File
Binary file not shown.
+48
View File
@@ -0,0 +1,48 @@
---
- name: Сброс пароля root MariaDB
hosts: all
become: yes
gather_facts: yes
tasks:
- name: Stop MariaDB service
ansible.builtin.systemd:
name: mariadb
state: stopped
- name: Start MariaDB in safe mode with skip-grant-tables
ansible.builtin.shell: |
mysqld_safe --skip-grant-tables &
sleep 5
async: 10
poll: 0
- name: Reset root password
ansible.builtin.shell: |
mysql -u root << EOF
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mariadb_root_password }}';
FLUSH PRIVILEGES;
EOF
- name: Stop MariaDB safe mode
ansible.builtin.systemd:
name: mariadb
state: stopped
- name: Start MariaDB normally
ansible.builtin.systemd:
name: mariadb
state: started
enabled: yes
- name: Create .my.cnf file for root user
ansible.builtin.copy:
content: |
[client]
user=root
password={{ mariadb_root_password }}
dest: /root/.my.cnf
mode: '0600'
owner: root
group: root
+5
View File
@@ -0,0 +1,5 @@
---
- name: Restart Apache
ansible.builtin.systemd:
name: apache2
state: restarted
+49
View File
@@ -0,0 +1,49 @@
---
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Install Apache
ansible.builtin.apt:
name: apache2
state: present
- name: Enable mod_rewrite
ansible.builtin.command:
cmd: a2enmod rewrite
creates: /etc/apache2/mods-enabled/rewrite.load
notify: Restart Apache
- name: Create website root directory
ansible.builtin.file:
path: "/var/www/{{ domain_name }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
- name: Configure virtual host
ansible.builtin.template:
src: vhost.conf.j2
dest: "/etc/apache2/sites-available/{{ domain_name }}.conf"
mode: '0644'
notify: Restart Apache
- name: Enable virtual host
ansible.builtin.command:
cmd: "a2ensite {{ domain_name }}.conf"
creates: "/etc/apache2/sites-enabled/{{ domain_name }}.conf"
notify: Restart Apache
- name: Disable default site
ansible.builtin.command:
cmd: a2dissite 000-default.conf
ignore_errors: yes
notify: Restart Apache
- name: Start and enable Apache
ansible.builtin.systemd:
name: apache2
state: started
enabled: yes
+13
View File
@@ -0,0 +1,13 @@
<VirtualHost *:80>
ServerName {{ domain_name }}
DocumentRoot /var/www/{{ domain_name }}
<Directory /var/www/{{ domain_name }}>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
+5
View File
@@ -0,0 +1,5 @@
---
mariadb_root_password: "CHANGE_ME"
app_db_name: "CHANGE_ME"
app_db_user: "CHANGE_ME"
app_db_password: "CHANGE_ME"
+5
View File
@@ -0,0 +1,5 @@
---
- name: Restart MariaDB
ansible.builtin.systemd:
name: mariadb
state: restarted
+113
View File
@@ -0,0 +1,113 @@
---
- name: Check if MariaDB is already installed
ansible.builtin.command: dpkg -l mariadb-server
register: mariadb_installed
failed_when: false
changed_when: false
- name: Check if MariaDB is running
ansible.builtin.systemd:
name: mariadb
register: mariadb_status
failed_when: false
changed_when: false
- name: Install MariaDB server (if not installed)
block:
- name: Install MariaDB packages
ansible.builtin.apt:
name:
- mariadb-server
- mariadb-client
- python3-pymysql
state: present
update_cache: yes
- name: Start and enable MariaDB
ansible.builtin.systemd:
name: mariadb
state: started
enabled: yes
when: mariadb_installed.rc != 0
- name: Check current root authentication method
ansible.builtin.shell: |
sudo mysql -e "SELECT plugin FROM mysql.user WHERE user='root' AND host='localhost';" -s -N
register: root_plugin
changed_when: false
ignore_errors: yes
- name: Switch root authentication from unix_socket to password
ansible.builtin.shell: |
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mariadb_root_password }}';"
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ mariadb_root_password }}';"
sudo mysql -e "FLUSH PRIVILEGES;"
when: root_plugin.stdout == 'unix_socket'
changed_when: true
- name: Create .my.cnf for root user
ansible.builtin.copy:
content: |
[client]
user=root
password={{ mariadb_root_password }}
dest: /root/.my.cnf
mode: '0600'
owner: root
group: root
- name: Test MySQL connection with password
ansible.builtin.command: mysql -u root -p{{ mariadb_root_password }} -e "SELECT 1"
register: mysql_test
changed_when: false
ignore_errors: yes
- name: Remove anonymous users
community.mysql.mysql_user:
name: ""
host_all: yes
login_user: root
login_password: "{{ mariadb_root_password }}"
state: absent
ignore_errors: yes
- name: Remove test database
community.mysql.mysql_db:
name: test
login_user: root
login_password: "{{ mariadb_root_password }}"
state: absent
ignore_errors: yes
- name: Check if database exists
ansible.builtin.command: mysql -u root -p{{ mariadb_root_password }} -e "USE {{ app_db_name }}"
register: db_exists
failed_when: false
changed_when: false
ignore_errors: yes
- name: Create osTicket database (if not exists)
community.mysql.mysql_db:
name: "{{ app_db_name }}"
login_user: root
login_password: "{{ mariadb_root_password }}"
state: present
when: db_exists.rc != 0
- name: Check if user exists
ansible.builtin.command: mysql -u root -p{{ mariadb_root_password }} -e "SELECT User FROM mysql.user WHERE User='{{ app_db_user }}'"
register: user_exists
failed_when: false
changed_when: false
ignore_errors: yes
- name: Create osTicket database user (if not exists)
community.mysql.mysql_user:
name: "{{ app_db_user }}"
password: "{{ app_db_password }}"
priv: "{{ app_db_name }}.*:ALL"
host: localhost
login_user: root
login_password: "{{ mariadb_root_password }}"
state: present
when: user_exists.rc != 0
+102
View File
@@ -0,0 +1,102 @@
---
- name: Install unzip
ansible.builtin.apt:
name: unzip
state: present
- name: Copy local osTicket ZIP to remote server
ansible.builtin.copy:
src: "{{ playbook_dir }}/osTicket.zip"
dest: /tmp/osticket.zip
mode: '0644'
- name: Create temp extraction directory
ansible.builtin.file:
path: /tmp/osticket_extract
state: directory
mode: '0755'
- name: Extract osTicket ZIP to temp directory
ansible.builtin.unarchive:
src: /tmp/osticket.zip
dest: /tmp/osticket_extract
remote_src: yes
- name: Find upload directory in extracted files
ansible.builtin.find:
paths: /tmp/osticket_extract
patterns: "upload"
file_type: directory
register: upload_dir
- name: Debug - show found upload directory
ansible.builtin.debug:
msg: "Upload directory found at: {{ upload_dir.files[0].path if upload_dir.files else 'NOT FOUND' }}"
- name: Copy files to webroot (if upload directory found)
ansible.builtin.copy:
src: "{{ upload_dir.files[0].path }}/"
dest: "/var/www/{{ domain_name }}/"
remote_src: yes
owner: www-data
group: www-data
mode: '0755'
when: upload_dir.files
- name: Copy all files to webroot (if no upload directory)
ansible.builtin.copy:
src: "/tmp/osticket_extract/"
dest: "/var/www/{{ domain_name }}/"
remote_src: yes
owner: www-data
group: www-data
mode: '0755'
when: not upload_dir.files
- name: Check if sample config exists
ansible.builtin.stat:
path: "/var/www/{{ domain_name }}/include/ost-sampleconfig.php"
register: sample_config
- name: Copy configuration file
ansible.builtin.copy:
src: "/var/www/{{ domain_name }}/include/ost-sampleconfig.php"
dest: "/var/www/{{ domain_name }}/include/ost-config.php"
owner: www-data
group: www-data
mode: '0666'
remote_src: yes
when: sample_config.stat.exists
- name: Set correct permissions
ansible.builtin.file:
path: "/var/www/{{ domain_name }}/include"
state: directory
owner: www-data
group: www-data
mode: '0755'
recurse: yes
- name: Create attachment directory
ansible.builtin.file:
path: "/var/www/{{ domain_name }}/attachments"
state: directory
owner: www-data
group: www-data
mode: '0777'
- name: Clean up temp files
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /tmp/osticket.zip
- /tmp/osticket_extract
- name: Display completion message
ansible.builtin.debug:
msg:
- "✅ osTicket successfully installed!"
- "📍 Access web installer at: http://{{ domain_name }}/"
- "⚠️ Complete setup via browser"
- "🔒 After installation, run: chmod 0644 /var/www/{{ domain_name }}/include/ost-config.php"
+46
View File
@@ -0,0 +1,46 @@
---
- name: Install prerequisite packages for PHP repository
ansible.builtin.apt:
name:
- ca-certificates
- curl
- gpg
state: present
- name: Add PHP repository key (Ondrej)
ansible.builtin.shell: |
curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/sury-php.gpg
args:
creates: /etc/apt/trusted.gpg.d/sury-php.gpg
- name: Add PHP repository
ansible.builtin.apt_repository:
repo: "deb https://packages.sury.org/php/ {{ ansible_facts['lsb']['codename'] }} main"
state: present
update_cache: yes
- name: Install PHP 8.4 and extensions
ansible.builtin.apt:
name:
- php8.4
- libapache2-mod-php8.4
- php8.4-mysql
- php8.4-cli
- php8.4-curl
- php8.4-gd
- php8.4-mbstring
- php8.4-xml
- php8.4-zip
- php8.4-intl
- php8.4-bcmath
- php8.4-imap
state: present
notify: Restart Apache
- name: Set index.php priority
ansible.builtin.lineinfile:
path: /etc/apache2/mods-enabled/dir.conf
regexp: '^(\s*DirectoryIndex)'
line: '\1 index.php index.html index.cgi index.pl index.xhtml index.htm'
backrefs: yes
notify: Restart Apache
+9
View File
@@ -0,0 +1,9 @@
---
- name: Настройка sudo для пользователя без пароля
ansible.builtin.lineinfile:
path: /etc/sudoers
state: present
regexp: '^{{ ansible_user }} ALL='
line: '{{ ansible_user }} ALL=(ALL) NOPASSWD:ALL'
validate: 'visudo -cf %s'
when: ansible_user != 'root'
Executable
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# Переходим в папку с плейбуком
cd /home/ogrechko/osticket-ansible
# Становимся root и запускаем ansible
sudo -i << 'SUDO'
cd /home/ogrechko/osticket-ansible
ansible-playbook install.yml
SUDO