mirror of
https://github.com/frappe/frappe_docker.git
synced 2024-11-08 14:21:05 +00:00
chore(lint): Run prettier
This commit is contained in:
parent
8b4dfce4f0
commit
fb07581595
14
.github/workflows/greetings.yml
vendored
14
.github/workflows/greetings.yml
vendored
@ -6,10 +6,10 @@ jobs:
|
|||||||
greeting:
|
greeting:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/first-interaction@v1
|
- uses: actions/first-interaction@v1
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
issue-message: |
|
issue-message: |
|
||||||
Hello! We're very happy to see your first issue. If your issue is about a problem, go back and check you have copy-pasted all the debug logs you can so we can help you as fast as possible!
|
Hello! We're very happy to see your first issue. If your issue is about a problem, go back and check you have copy-pasted all the debug logs you can so we can help you as fast as possible!
|
||||||
pr-message: |
|
pr-message: |
|
||||||
Hello! Thank you about this PR. Since this is your first PR, please make sure you have described the improvements and your code is well documented.
|
Hello! Thank you about this PR. Since this is your first PR, please make sure you have described the improvements and your code is well documented.
|
||||||
|
16
.vscode/extensions.json
vendored
16
.vscode/extensions.json
vendored
@ -1,13 +1,9 @@
|
|||||||
{
|
{
|
||||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
// List of extensions which should be recommended for users of this workspace.
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
"recommendations": [
|
"recommendations": ["ms-vscode-remote.remote-containers"],
|
||||||
"ms-vscode-remote.remote-containers"
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
],
|
"unwantedRecommendations": []
|
||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
|
||||||
"unwantedRecommendations": [
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
|
|||||||
Examples of behavior that contributes to creating a positive environment
|
Examples of behavior that contributes to creating a positive environment
|
||||||
include:
|
include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances
|
advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic
|
- Publishing others' private information, such as a physical or electronic
|
||||||
address, without explicit permission
|
address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
|
|
||||||
|
@ -7,9 +7,8 @@ Before publishing a PR, please test builds locally:
|
|||||||
- with VSCode for testing environments (only for frappe/bench image).
|
- with VSCode for testing environments (only for frappe/bench image).
|
||||||
|
|
||||||
On each PR that contains changes relevant to Docker builds, images are being built and tested in our CI (GitHub Actions).
|
On each PR that contains changes relevant to Docker builds, images are being built and tested in our CI (GitHub Actions).
|
||||||
> :evergreen_tree: Please be considerate when pushing commits and opening PR for multiple branches, as the process of building images uses energy and contributes to global warming.
|
|
||||||
>
|
|
||||||
|
|
||||||
|
> :evergreen_tree: Please be considerate when pushing commits and opening PR for multiple branches, as the process of building images uses energy and contributes to global warming.
|
||||||
|
|
||||||
## Lint
|
## Lint
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ To run all the files in repository, run:
|
|||||||
pre-commit run --all-files
|
pre-commit run --all-files
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@ -52,20 +50,25 @@ docker buildx bake -f docker-bake.hcl *...*
|
|||||||
## Test
|
## Test
|
||||||
|
|
||||||
### Ping site
|
### Ping site
|
||||||
|
|
||||||
Lightweight test that just checks if site will be available after creation.
|
Lightweight test that just checks if site will be available after creation.
|
||||||
|
|
||||||
Frappe:
|
Frappe:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./tests/test-frappe.sh
|
./tests/test-frappe.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
ERPNext:
|
ERPNext:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./tests/test-erpnext.sh
|
./tests/test-erpnext.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Integration test
|
### Integration test
|
||||||
|
|
||||||
Tests frappe-bench-like commands, for example, `backup` and `restore`.
|
Tests frappe-bench-like commands, for example, `backup` and `restore`.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./tests/integration-test.sh
|
./tests/integration-test.sh
|
||||||
```
|
```
|
||||||
|
18
README.md
18
README.md
@ -30,21 +30,21 @@ cd frappe_docker
|
|||||||
|
|
||||||
It takes care of the following:
|
It takes care of the following:
|
||||||
|
|
||||||
* Setting up the desired version of Frappe/ERPNext.
|
- Setting up the desired version of Frappe/ERPNext.
|
||||||
* Setting up all the system requirements: eg. MariaDB, Node, Redis.
|
- Setting up all the system requirements: eg. MariaDB, Node, Redis.
|
||||||
* Configure networking for remote access and setting up LetsEncrypt.
|
- Configure networking for remote access and setting up LetsEncrypt.
|
||||||
|
|
||||||
It doesn't take care of the following:
|
It doesn't take care of the following:
|
||||||
|
|
||||||
* Cron Job to backup sites is not created by default.
|
- Cron Job to backup sites is not created by default.
|
||||||
* Use `CronJob` on k8s or refer wiki for alternatives.
|
- Use `CronJob` on k8s or refer wiki for alternatives.
|
||||||
|
|
||||||
1. Single Server Installs
|
1. Single Server Installs
|
||||||
1. [Single bench](docs/single-bench.md). Easiest Install!
|
1. [Single bench](docs/single-bench.md). Easiest Install!
|
||||||
2. [Multi bench](docs/multi-bench.md)
|
2. [Multi bench](docs/multi-bench.md)
|
||||||
2. Multi Server Installs
|
2. Multi Server Installs
|
||||||
1. [Docker Swarm](docs/docker-swarm.md)
|
1. [Docker Swarm](docs/docker-swarm.md)
|
||||||
2. [Kubernetes](https://helm.erpnext.com)
|
2. [Kubernetes](https://helm.erpnext.com)
|
||||||
3. [Site Operations](docs/site-operations.md)
|
3. [Site Operations](docs/site-operations.md)
|
||||||
4. [Environment Variables](docs/environment-variables.md)
|
4. [Environment Variables](docs/environment-variables.md)
|
||||||
5. [Custom apps for production](docs/custom-apps-for-production.md)
|
5. [Custom apps for production](docs/custom-apps-for-production.md)
|
||||||
|
@ -44,14 +44,14 @@ If you want to use PostgreSQL instead, edit `.devcontainer/docker-compose.yml` a
|
|||||||
VSCode should automatically inquire you to install the required extensions, that can also be installed manually as follows:
|
VSCode should automatically inquire you to install the required extensions, that can also be installed manually as follows:
|
||||||
|
|
||||||
- Install Remote - Containers for VSCode
|
- Install Remote - Containers for VSCode
|
||||||
- through command line `code --install-extension ms-vscode-remote.remote-containers`
|
- through command line `code --install-extension ms-vscode-remote.remote-containers`
|
||||||
- clicking on the Install button in the Vistual Studio Marketplace: [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
- clicking on the Install button in the Vistual Studio Marketplace: [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
||||||
- View: Extensions command in VSCode (Windows: Ctrl+Shift+X; macOS: Cmd+Shift+X) then search for extension `ms-vscode-remote.remote-containers`
|
- View: Extensions command in VSCode (Windows: Ctrl+Shift+X; macOS: Cmd+Shift+X) then search for extension `ms-vscode-remote.remote-containers`
|
||||||
|
|
||||||
After the extensions are installed, you can:
|
After the extensions are installed, you can:
|
||||||
|
|
||||||
- Open frappe_docker folder in VS Code.
|
- Open frappe_docker folder in VS Code.
|
||||||
- `code .`
|
- `code .`
|
||||||
- Launch the command, from Command Palette (Ctrl + Shift + P) `Execute Remote Containers : Reopen in Container`. You can also click in the bottom left corner to access the remote container menu.
|
- Launch the command, from Command Palette (Ctrl + Shift + P) `Execute Remote Containers : Reopen in Container`. You can also click in the bottom left corner to access the remote container menu.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
@ -94,6 +94,7 @@ code Procfile
|
|||||||
```
|
```
|
||||||
|
|
||||||
Or running the following command:
|
Or running the following command:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sed -i '/redis/d' ./Procfile
|
sed -i '/redis/d' ./Procfile
|
||||||
```
|
```
|
||||||
@ -105,6 +106,7 @@ You can create a new site with the following command:
|
|||||||
```shell
|
```shell
|
||||||
bench new-site sitename --no-mariadb-socket
|
bench new-site sitename --no-mariadb-socket
|
||||||
```
|
```
|
||||||
|
|
||||||
sitename MUST end with .localhost for trying deployments locally.
|
sitename MUST end with .localhost for trying deployments locally.
|
||||||
|
|
||||||
for example:
|
for example:
|
||||||
@ -259,7 +261,6 @@ Example shows the queries to be executed for site `localhost`
|
|||||||
|
|
||||||
Open sites/localhost/site_config.json:
|
Open sites/localhost/site_config.json:
|
||||||
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
code sites/localhost/site_config.json
|
code sites/localhost/site_config.json
|
||||||
```
|
```
|
||||||
@ -286,6 +287,7 @@ EXIT;
|
|||||||
In case you don't use VSCode, you may start the containers manually with the following command:
|
In case you don't use VSCode, you may start the containers manually with the following command:
|
||||||
|
|
||||||
### Running the containers
|
### Running the containers
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker-compose -f .devcontainer/docker-compose.yml up -d
|
docker-compose -f .devcontainer/docker-compose.yml up -d
|
||||||
```
|
```
|
||||||
|
@ -1,76 +1,81 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
// Use IntelliSense to learn about possible attributes.
|
||||||
// Hover to view descriptions of existing attributes.
|
// Hover to view descriptions of existing attributes.
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Bench Web",
|
"name": "Bench Web",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||||
"args": [
|
"args": [
|
||||||
"frappe", "serve", "--port", "8000", "--noreload", "--nothreading"
|
"frappe",
|
||||||
],
|
"serve",
|
||||||
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
"--port",
|
||||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
"8000",
|
||||||
"env": {
|
"--noreload",
|
||||||
"DEV_SERVER": "1"
|
"--nothreading"
|
||||||
}
|
],
|
||||||
},
|
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
||||||
{
|
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||||
"name": "Bench Default Worker",
|
"env": {
|
||||||
"type": "python",
|
"DEV_SERVER": "1"
|
||||||
"request": "launch",
|
}
|
||||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
},
|
||||||
"args": [
|
{
|
||||||
"frappe", "worker", "--queue", "default"
|
"name": "Bench Default Worker",
|
||||||
],
|
"type": "python",
|
||||||
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
"request": "launch",
|
||||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||||
"env": {
|
"args": ["frappe", "worker", "--queue", "default"],
|
||||||
"DEV_SERVER": "1"
|
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
||||||
}
|
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||||
},
|
"env": {
|
||||||
{
|
"DEV_SERVER": "1"
|
||||||
"name": "Bench Short Worker",
|
}
|
||||||
"type": "python",
|
},
|
||||||
"request": "launch",
|
{
|
||||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
"name": "Bench Short Worker",
|
||||||
"args": [
|
"type": "python",
|
||||||
"frappe", "worker", "--queue", "short"
|
"request": "launch",
|
||||||
],
|
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||||
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
"args": ["frappe", "worker", "--queue", "short"],
|
||||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
||||||
"env": {
|
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||||
"DEV_SERVER": "1"
|
"env": {
|
||||||
}
|
"DEV_SERVER": "1"
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
"name": "Bench Long Worker",
|
{
|
||||||
"type": "python",
|
"name": "Bench Long Worker",
|
||||||
"request": "launch",
|
"type": "python",
|
||||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
"request": "launch",
|
||||||
"args": [
|
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||||
"frappe", "worker", "--queue", "long"
|
"args": ["frappe", "worker", "--queue", "long"],
|
||||||
],
|
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
||||||
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
"env": {
|
||||||
"env": {
|
"DEV_SERVER": "1"
|
||||||
"DEV_SERVER": "1"
|
}
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
{
|
"name": "Honcho SocketIO Watch Schedule Worker",
|
||||||
"name": "Honcho SocketIO Watch Schedule Worker",
|
"type": "python",
|
||||||
"type": "python",
|
"request": "launch",
|
||||||
"request": "launch",
|
"program": "/home/frappe/.local/bin/honcho",
|
||||||
"program": "/home/frappe/.local/bin/honcho",
|
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
||||||
"pythonPath": "${workspaceFolder}/frappe-bench/env/bin/python",
|
"cwd": "${workspaceFolder}/frappe-bench",
|
||||||
"cwd": "${workspaceFolder}/frappe-bench",
|
"console": "internalConsole",
|
||||||
"console": "internalConsole",
|
"args": [
|
||||||
"args": [
|
"start",
|
||||||
"start", "socketio", "watch", "schedule", "worker_short", "worker_long", "worker_default"
|
"socketio",
|
||||||
]
|
"watch",
|
||||||
}
|
"schedule",
|
||||||
]
|
"worker_short",
|
||||||
|
"worker_long",
|
||||||
|
"worker_default"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"debug.node.autoAttach": "disabled"
|
"debug.node.autoAttach": "disabled"
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ version: "3.7"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
mariadb-master:
|
mariadb-master:
|
||||||
image: 'bitnami/mariadb:10.3'
|
image: "bitnami/mariadb:10.3"
|
||||||
deploy:
|
deploy:
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
@ -54,7 +54,7 @@ services:
|
|||||||
secrets:
|
secrets:
|
||||||
- frappe-mariadb-root-password
|
- frappe-mariadb-root-password
|
||||||
volumes:
|
volumes:
|
||||||
- 'mariadb_master_data:/bitnami/mariadb'
|
- "mariadb_master_data:/bitnami/mariadb"
|
||||||
environment:
|
environment:
|
||||||
- MARIADB_REPLICATION_MODE=master
|
- MARIADB_REPLICATION_MODE=master
|
||||||
- MARIADB_REPLICATION_USER=repl_user
|
- MARIADB_REPLICATION_USER=repl_user
|
||||||
@ -62,7 +62,7 @@ services:
|
|||||||
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password
|
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password
|
||||||
|
|
||||||
mariadb-slave:
|
mariadb-slave:
|
||||||
image: 'bitnami/mariadb:10.3'
|
image: "bitnami/mariadb:10.3"
|
||||||
deploy:
|
deploy:
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
@ -74,7 +74,7 @@ services:
|
|||||||
secrets:
|
secrets:
|
||||||
- frappe-mariadb-root-password
|
- frappe-mariadb-root-password
|
||||||
volumes:
|
volumes:
|
||||||
- 'mariadb_slave_data:/bitnami/mariadb'
|
- "mariadb_slave_data:/bitnami/mariadb"
|
||||||
environment:
|
environment:
|
||||||
- MARIADB_REPLICATION_MODE=slave
|
- MARIADB_REPLICATION_MODE=slave
|
||||||
- MARIADB_REPLICATION_USER=repl_user
|
- MARIADB_REPLICATION_USER=repl_user
|
||||||
@ -265,6 +265,7 @@ Use environment variables:
|
|||||||
- `FRAPPE_VERSION` variable to be set to desired version of Frappe Framework. e.g. 12.7.0
|
- `FRAPPE_VERSION` variable to be set to desired version of Frappe Framework. e.g. 12.7.0
|
||||||
- `MARIADB_HOST=frappe-mariadb_mariadb-master`
|
- `MARIADB_HOST=frappe-mariadb_mariadb-master`
|
||||||
- `SITES` variable is list of sites in back tick and separated by comma
|
- `SITES` variable is list of sites in back tick and separated by comma
|
||||||
|
|
||||||
```
|
```
|
||||||
SITES=`site1.example.com`,`site2.example.com`
|
SITES=`site1.example.com`,`site2.example.com`
|
||||||
```
|
```
|
||||||
@ -277,9 +278,9 @@ SITES=`site1.example.com`,`site2.example.com`
|
|||||||
4. Select network `frappe-network`
|
4. Select network `frappe-network`
|
||||||
5. Select Volume `frappe-bench-v13_sites-vol` and mount in container `/home/frappe/frappe-bench/sites`
|
5. Select Volume `frappe-bench-v13_sites-vol` and mount in container `/home/frappe/frappe-bench/sites`
|
||||||
6. Env variables:
|
6. Env variables:
|
||||||
- MYSQL_ROOT_PASSWORD=longsecretpassword
|
- MYSQL_ROOT_PASSWORD=longsecretpassword
|
||||||
- SITE_NAME=site1.example.com
|
- SITE_NAME=site1.example.com
|
||||||
- INSTALL_APPS=erpnext
|
- INSTALL_APPS=erpnext
|
||||||
7. Start container
|
7. Start container
|
||||||
|
|
||||||
### Migrate Sites job
|
### Migrate Sites job
|
||||||
@ -290,5 +291,5 @@ SITES=`site1.example.com`,`site2.example.com`
|
|||||||
4. Select network `frappe-network`
|
4. Select network `frappe-network`
|
||||||
5. Select Volume `frappe-bench-v13_sites-vol` and mount in container `/home/frappe/frappe-bench/sites`
|
5. Select Volume `frappe-bench-v13_sites-vol` and mount in container `/home/frappe/frappe-bench/sites`
|
||||||
6. Env variables:
|
6. Env variables:
|
||||||
- MAINTENANCE_MODE=1
|
- MAINTENANCE_MODE=1
|
||||||
7. Start container
|
7. Start container
|
||||||
|
@ -17,17 +17,17 @@ cp env-example .env
|
|||||||
To get started, copy the existing `env-example` file to `.env`. By default, the file will contain the following variables:
|
To get started, copy the existing `env-example` file to `.env`. By default, the file will contain the following variables:
|
||||||
|
|
||||||
- `VERSION=edge`
|
- `VERSION=edge`
|
||||||
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11)
|
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11)
|
||||||
- `MYSQL_ROOT_PASSWORD=admin`
|
- `MYSQL_ROOT_PASSWORD=admin`
|
||||||
- Bootstraps a MariaDB container with this value set as the root password. If a managed MariaDB instance is used, there is no need to set the password here.
|
- Bootstraps a MariaDB container with this value set as the root password. If a managed MariaDB instance is used, there is no need to set the password here.
|
||||||
- `MARIADB_HOST=mariadb`
|
- `MARIADB_HOST=mariadb`
|
||||||
- Sets the hostname to `mariadb`. This is required if the database is managed by the containerized MariaDB instance.
|
- Sets the hostname to `mariadb`. This is required if the database is managed by the containerized MariaDB instance.
|
||||||
- In case of a separately managed database setups, set the value to the database's hostname/IP/domain.
|
- In case of a separately managed database setups, set the value to the database's hostname/IP/domain.
|
||||||
- `SITES=site1.domain.com,site2.domain.com`
|
- `SITES=site1.domain.com,site2.domain.com`
|
||||||
- List of sites that are part of the deployment "bench" Each site is separated by a comma(,).
|
- List of sites that are part of the deployment "bench" Each site is separated by a comma(,).
|
||||||
- If LetsEncrypt is being setup, make sure that the DNS for all the site's domains correctly point to the current instance.
|
- If LetsEncrypt is being setup, make sure that the DNS for all the site's domains correctly point to the current instance.
|
||||||
- `LETSENCRYPT_EMAIL=your.email@your.domain.com`
|
- `LETSENCRYPT_EMAIL=your.email@your.domain.com`
|
||||||
- Email for LetsEncrypt expiry notification. This is only required if you are setting up LetsEncrypt.
|
- Email for LetsEncrypt expiry notification. This is only required if you are setting up LetsEncrypt.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
@ -123,46 +123,49 @@ Notes:
|
|||||||
## Docker containers
|
## Docker containers
|
||||||
|
|
||||||
This repository contains the following docker-compose files, each one containing the described images:
|
This repository contains the following docker-compose files, each one containing the described images:
|
||||||
* docker-compose-common.yml
|
|
||||||
* redis-cache
|
|
||||||
* volume: redis-cache-vol
|
|
||||||
* redis-queue
|
|
||||||
* volume: redis-queue-vol
|
|
||||||
* redis-socketio
|
|
||||||
* volume: redis-socketio-vol
|
|
||||||
* mariadb: main database
|
|
||||||
* volume: mariadb-vol
|
|
||||||
* docker-compose-erpnext.yml
|
|
||||||
* erpnext-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
|
||||||
* volume: assets-vol
|
|
||||||
* erpnext-python: main application code
|
|
||||||
* frappe-socketio: enables realtime communication to the user interface through websockets
|
|
||||||
* frappe-worker-default: background runner
|
|
||||||
* frappe-worker-short: background runner for short-running jobs
|
|
||||||
* frappe-worker-long: background runner for long-running jobs
|
|
||||||
* frappe-schedule
|
|
||||||
|
|
||||||
* docker-compose-frappe.yml
|
- docker-compose-common.yml
|
||||||
* frappe-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
- redis-cache
|
||||||
* volume: assets-vol, sites-vol
|
- volume: redis-cache-vol
|
||||||
* erpnext-python: main application code
|
- redis-queue
|
||||||
* volume: sites-vol
|
- volume: redis-queue-vol
|
||||||
* frappe-socketio: enables realtime communication to the user interface through websockets
|
- redis-socketio
|
||||||
* volume: sites-vol
|
- volume: redis-socketio-vol
|
||||||
* frappe-worker-default: background runner
|
- mariadb: main database
|
||||||
* volume: sites-vol
|
- volume: mariadb-vol
|
||||||
* frappe-worker-short: background runner for short-running jobs
|
- docker-compose-erpnext.yml
|
||||||
* volume: sites-vol
|
|
||||||
* frappe-worker-long: background runner for long-running jobs
|
|
||||||
* volume: sites-vol
|
|
||||||
* frappe-schedule
|
|
||||||
* volume: sites-vol
|
|
||||||
|
|
||||||
* docker-compose-networks.yml: this yaml define the network to communicate with *Letsencrypt Nginx Proxy Companion*.
|
- erpnext-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
||||||
|
- volume: assets-vol
|
||||||
|
- erpnext-python: main application code
|
||||||
|
- frappe-socketio: enables realtime communication to the user interface through websockets
|
||||||
|
- frappe-worker-default: background runner
|
||||||
|
- frappe-worker-short: background runner for short-running jobs
|
||||||
|
- frappe-worker-long: background runner for long-running jobs
|
||||||
|
- frappe-schedule
|
||||||
|
|
||||||
* erpnext-publish.yml: this yml extends erpnext-nginx service to publish port 80, can only be used with docker-compose-erpnext.yml
|
- docker-compose-frappe.yml
|
||||||
|
|
||||||
* frappe-publish.yml: this yml extends frappe-nginx service to publish port 80, can only be used with docker-compose-frappe.yml
|
- frappe-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
||||||
|
- volume: assets-vol, sites-vol
|
||||||
|
- erpnext-python: main application code
|
||||||
|
- volume: sites-vol
|
||||||
|
- frappe-socketio: enables realtime communication to the user interface through websockets
|
||||||
|
- volume: sites-vol
|
||||||
|
- frappe-worker-default: background runner
|
||||||
|
- volume: sites-vol
|
||||||
|
- frappe-worker-short: background runner for short-running jobs
|
||||||
|
- volume: sites-vol
|
||||||
|
- frappe-worker-long: background runner for long-running jobs
|
||||||
|
- volume: sites-vol
|
||||||
|
- frappe-schedule
|
||||||
|
- volume: sites-vol
|
||||||
|
|
||||||
|
- docker-compose-networks.yml: this yaml define the network to communicate with _Letsencrypt Nginx Proxy Companion_.
|
||||||
|
|
||||||
|
- erpnext-publish.yml: this yml extends erpnext-nginx service to publish port 80, can only be used with docker-compose-erpnext.yml
|
||||||
|
|
||||||
|
- frappe-publish.yml: this yml extends frappe-nginx service to publish port 80, can only be used with docker-compose-frappe.yml
|
||||||
|
|
||||||
## Updating and Migrating Sites
|
## Updating and Migrating Sites
|
||||||
|
|
||||||
|
@ -26,39 +26,39 @@ cp env-production .env
|
|||||||
To get started, copy the existing `env-local` or `env-production` file to `.env`. By default, the file will contain the following variables:
|
To get started, copy the existing `env-local` or `env-production` file to `.env`. By default, the file will contain the following variables:
|
||||||
|
|
||||||
- `ERPNEXT_VERSION=edge`
|
- `ERPNEXT_VERSION=edge`
|
||||||
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11).
|
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11).
|
||||||
- `FRAPPE_VERSION=edge`
|
- `FRAPPE_VERSION=edge`
|
||||||
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11).
|
- In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. v13.0.0, version-12, v11.1.15, v11).
|
||||||
- `MARIADB_HOST=mariadb`
|
- `MARIADB_HOST=mariadb`
|
||||||
- Sets the hostname to `mariadb`. This is required if the database is managed by the containerized MariaDB instance.
|
- Sets the hostname to `mariadb`. This is required if the database is managed by the containerized MariaDB instance.
|
||||||
- `MYSQL_ROOT_PASSWORD=admin`
|
- `MYSQL_ROOT_PASSWORD=admin`
|
||||||
- Bootstraps a MariaDB container with this value set as the root password. If a managed MariaDB instance is used, there is no need to set the password here.
|
- Bootstraps a MariaDB container with this value set as the root password. If a managed MariaDB instance is used, there is no need to set the password here.
|
||||||
- In case of a separately managed database setups, set the value to the database's hostname/IP/domain.
|
- In case of a separately managed database setups, set the value to the database's hostname/IP/domain.
|
||||||
- `SITE_NAME=erp.example.com`
|
- `SITE_NAME=erp.example.com`
|
||||||
- Creates this site after starting all services and installs ERPNext. Site name must be resolvable by users machines and the ERPNext components. e.g. `erp.example.com` or `mysite.localhost`.
|
- Creates this site after starting all services and installs ERPNext. Site name must be resolvable by users machines and the ERPNext components. e.g. `erp.example.com` or `mysite.localhost`.
|
||||||
- ``SITES=`erp.example.com` ``
|
- `` SITES=`erp.example.com` ``
|
||||||
- List of sites that are part of the deployment "bench" Each site is separated by a comma(,) and quoted in backtick (`). By default site created by ``SITE_NAME`` variable is added here.
|
- List of sites that are part of the deployment "bench" Each site is separated by a comma(,) and quoted in backtick (`). By default site created by `SITE_NAME` variable is added here.
|
||||||
- If LetsEncrypt is being setup, make sure that the DNS for all the site's domains correctly point to the current instance.
|
- If LetsEncrypt is being setup, make sure that the DNS for all the site's domains correctly point to the current instance.
|
||||||
- `DB_ROOT_USER=root`
|
- `DB_ROOT_USER=root`
|
||||||
- MariaDB root username
|
- MariaDB root username
|
||||||
- `ADMIN_PASSWORD=admin`
|
- `ADMIN_PASSWORD=admin`
|
||||||
- Password for the `Administrator` user, credentials after install `Administrator:$ADMIN_PASSWORD`.
|
- Password for the `Administrator` user, credentials after install `Administrator:$ADMIN_PASSWORD`.
|
||||||
- `INSTALL_APPS=erpnext`
|
- `INSTALL_APPS=erpnext`
|
||||||
- Apps to install, the app must be already in the container image, to install other application read the [instructions on installing custom apps](./custom-apps-for-production.md).
|
- Apps to install, the app must be already in the container image, to install other application read the [instructions on installing custom apps](./custom-apps-for-production.md).
|
||||||
- `LETSENCRYPT_EMAIL=email@example.com`
|
- `LETSENCRYPT_EMAIL=email@example.com`
|
||||||
- Email for LetsEncrypt expiry notification. This is only required if you are setting up LetsEncrypt.
|
- Email for LetsEncrypt expiry notification. This is only required if you are setting up LetsEncrypt.
|
||||||
- `ENTRYPOINT_LABEL=traefik.http.routers.erpnext-nginx.entrypoints=websecure`
|
- `ENTRYPOINT_LABEL=traefik.http.routers.erpnext-nginx.entrypoints=websecure`
|
||||||
- Related to the traefik configuration, says all traffic from outside should come from HTTP or HTTPS, for local development should be web, for production websecure. if redirection is needed, read below.
|
- Related to the traefik configuration, says all traffic from outside should come from HTTP or HTTPS, for local development should be web, for production websecure. if redirection is needed, read below.
|
||||||
- `CERT_RESOLVER_LABEL=traefik.http.routers.erpnext-nginx.tls.certresolver=myresolver`
|
- `CERT_RESOLVER_LABEL=traefik.http.routers.erpnext-nginx.tls.certresolver=myresolver`
|
||||||
- Which traefik resolver to use to get TLS certificate, sets `erpnext.local.no-cert-resolver` for local setup.
|
- Which traefik resolver to use to get TLS certificate, sets `erpnext.local.no-cert-resolver` for local setup.
|
||||||
- ``HTTPS_REDIRECT_RULE_LABEL=traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`) ``
|
- `` HTTPS_REDIRECT_RULE_LABEL=traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`) ``
|
||||||
- Related to the traefik https redirection configuration, sets `erpnext.local.no-redirect-rule` for local setup.
|
- Related to the traefik https redirection configuration, sets `erpnext.local.no-redirect-rule` for local setup.
|
||||||
- `HTTPS_REDIRECT_ENTRYPOINT_LABEL=traefik.http.routers.http-catchall.entrypoints=web`
|
- `HTTPS_REDIRECT_ENTRYPOINT_LABEL=traefik.http.routers.http-catchall.entrypoints=web`
|
||||||
- Related to the traefik https redirection configuration, sets `erpnext.local.no-entrypoint` for local setup.
|
- Related to the traefik https redirection configuration, sets `erpnext.local.no-entrypoint` for local setup.
|
||||||
- `HTTPS_REDIRECT_MIDDLEWARE_LABEL=traefik.http.routers.http-catchall.middlewares=redirect-to-https`
|
- `HTTPS_REDIRECT_MIDDLEWARE_LABEL=traefik.http.routers.http-catchall.middlewares=redirect-to-https`
|
||||||
- Related to the traefik https redirection configuration, sets `erpnext.local.no-middleware` for local setup.
|
- Related to the traefik https redirection configuration, sets `erpnext.local.no-middleware` for local setup.
|
||||||
- `HTTPS_USE_REDIRECT_MIDDLEWARE_LABEL=traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https`
|
- `HTTPS_USE_REDIRECT_MIDDLEWARE_LABEL=traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https`
|
||||||
- Related to the traefik https redirection configuration, sets `erpnext.local-no-redirect-middleware` for local setup.
|
- Related to the traefik https redirection configuration, sets `erpnext.local-no-redirect-middleware` for local setup.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ Make sure to replace `<project-name>` with the desired name you wish to set for
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- If it is the first time running and site is being initialized, *it can take multiple minutes for the site to be up*. Monitor `site-creator` container logs to check progress. Use command `docker logs <project-name>_site-creator_1 -f`
|
- If it is the first time running and site is being initialized, _it can take multiple minutes for the site to be up_. Monitor `site-creator` container logs to check progress. Use command `docker logs <project-name>_site-creator_1 -f`
|
||||||
- After the site is ready the username is `Administrator` and the password is `$ADMIN_PASSWORD`
|
- After the site is ready the username is `Administrator` and the password is `$ADMIN_PASSWORD`
|
||||||
- The local deployment is for testing and REST API development purpose only
|
- The local deployment is for testing and REST API development purpose only
|
||||||
- A complete development environment is available [here](../development)
|
- A complete development environment is available [here](../development)
|
||||||
@ -86,32 +86,32 @@ Notes:
|
|||||||
|
|
||||||
The docker-compose file contains following services:
|
The docker-compose file contains following services:
|
||||||
|
|
||||||
* traefik: manages letsencrypt
|
- traefik: manages letsencrypt
|
||||||
* volume: cert-vol
|
- volume: cert-vol
|
||||||
* redis-cache: cache store
|
- redis-cache: cache store
|
||||||
* volume: redis-cache-vol
|
- volume: redis-cache-vol
|
||||||
* redis-queue: used by workers
|
- redis-queue: used by workers
|
||||||
* volume: redis-queue-vol
|
- volume: redis-queue-vol
|
||||||
* redis-socketio: used by socketio service
|
- redis-socketio: used by socketio service
|
||||||
* volume: redis-socketio-vol
|
- volume: redis-socketio-vol
|
||||||
* mariadb: main database
|
- mariadb: main database
|
||||||
* volume: mariadb-vol
|
- volume: mariadb-vol
|
||||||
* erpnext-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
- erpnext-nginx: serves static assets and proxies web request to the appropriate container, allowing to offer all services on the same port.
|
||||||
* volume: assets-vol and sites-vol
|
- volume: assets-vol and sites-vol
|
||||||
* erpnext-python: main application code
|
- erpnext-python: main application code
|
||||||
* volume: sites-vol and sites-vol
|
- volume: sites-vol and sites-vol
|
||||||
* frappe-socketio: enables realtime communication to the user interface through websockets
|
- frappe-socketio: enables realtime communication to the user interface through websockets
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
* erpnext-worker-default: background runner
|
- erpnext-worker-default: background runner
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
* erpnext-worker-short: background runner for short-running jobs
|
- erpnext-worker-short: background runner for short-running jobs
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
* erpnext-worker-long: background runner for long-running jobs
|
- erpnext-worker-long: background runner for long-running jobs
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
* erpnext-schedule
|
- erpnext-schedule
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
* site-creator: run once container to create new site.
|
- site-creator: run once container to create new site.
|
||||||
* volume: sites-vol
|
- volume: sites-vol
|
||||||
|
|
||||||
## Updating and Migrating Sites
|
## Updating and Migrating Sites
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ Or specify environment variables instead of passing secrets as command arguments
|
|||||||
Note:
|
Note:
|
||||||
|
|
||||||
- Wait for the database service to start before trying to create a new site.
|
- Wait for the database service to start before trying to create a new site.
|
||||||
- If new site creation fails, retry after the MariaDB container is up and running.
|
- If new site creation fails, retry after the MariaDB container is up and running.
|
||||||
- If you're using a managed database instance, make sure that the database is running before setting up a new site.
|
- If you're using a managed database instance, make sure that the database is running before setting up a new site.
|
||||||
|
|
||||||
#### MariaDB Site
|
#### MariaDB Site
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ Notes:
|
|||||||
|
|
||||||
## Add sites to proxy
|
## Add sites to proxy
|
||||||
|
|
||||||
Change `SITES` variable to the list of sites created encapsulated in backtick and separated by comma with no space. e.g. ``SITES=`site1.example.com`,`site2.example.com` ``.
|
Change `SITES` variable to the list of sites created encapsulated in backtick and separated by comma with no space. e.g. `` SITES=`site1.example.com`,`site2.example.com` ``.
|
||||||
|
|
||||||
Reload variables with following command.
|
Reload variables with following command.
|
||||||
|
|
||||||
@ -165,19 +165,19 @@ Note:
|
|||||||
- Volume must be mounted at location `/home/frappe/backups` for restoring sites
|
- Volume must be mounted at location `/home/frappe/backups` for restoring sites
|
||||||
- If no backup files are found in volume, it will use s3 credentials to pull backups
|
- If no backup files are found in volume, it will use s3 credentials to pull backups
|
||||||
- Backup structure for mounted volume or downloaded from s3:
|
- Backup structure for mounted volume or downloaded from s3:
|
||||||
- /home/frappe/backups
|
- /home/frappe/backups
|
||||||
- site1.domain.com
|
- site1.domain.com
|
||||||
- 20200420_162000
|
- 20200420_162000
|
||||||
- 20200420_162000-site1_domain_com-*
|
- 20200420_162000-site1_domain_com-\*
|
||||||
- site2.domain.com
|
- site2.domain.com
|
||||||
- 20200420_162000
|
- 20200420_162000
|
||||||
- 20200420_162000-site2_domain_com-*
|
- 20200420_162000-site2_domain_com-\*
|
||||||
|
|
||||||
## Edit configs
|
## Edit configs
|
||||||
|
|
||||||
Editing config manually might be required in some cases,
|
Editing config manually might be required in some cases,
|
||||||
one such case is to use Amazon RDS (or any other DBaaS).
|
one such case is to use Amazon RDS (or any other DBaaS).
|
||||||
For full instructions, refer to the [wiki](https://github.com/frappe/frappe/wiki/Using-Frappe-with-Amazon-RDS-(or-any-other-DBaaS)). Common question can be found in Issues and on forum.
|
For full instructions, refer to the [wiki](<https://github.com/frappe/frappe/wiki/Using-Frappe-with-Amazon-RDS-(or-any-other-DBaaS)>). Common question can be found in Issues and on forum.
|
||||||
|
|
||||||
`common_site_config.json` or `site_config.json` from `sites-vol` volume has to be edited using following command:
|
`common_site_config.json` or `site_config.json` from `sites-vol` volume has to be edited using following command:
|
||||||
|
|
||||||
@ -231,7 +231,6 @@ Notes:
|
|||||||
- Use it to install/uninstall custom apps, add system manager user, etc.
|
- Use it to install/uninstall custom apps, add system manager user, etc.
|
||||||
- To run the command as non root user add the command option `--user frappe`.
|
- To run the command as non root user add the command option `--user frappe`.
|
||||||
|
|
||||||
|
|
||||||
## Delete/Drop Site
|
## Delete/Drop Site
|
||||||
|
|
||||||
#### MariaDB Site
|
#### MariaDB Site
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
# Tips for moving deployments
|
# Tips for moving deployments
|
||||||
|
|
||||||
- Take regular automatic backups and push the files to S3 compatible cloud. Setup backup and push with cronjobs
|
- Take regular automatic backups and push the files to S3 compatible cloud. Setup backup and push with cronjobs
|
||||||
- Use regular cron for single machine installs
|
- Use regular cron for single machine installs
|
||||||
- Use [swarm-cronjob](https://github.com/crazy-max/swarm-cronjob) for docker swarm
|
- Use [swarm-cronjob](https://github.com/crazy-max/swarm-cronjob) for docker swarm
|
||||||
- Use Kubernetes CronJob
|
- Use Kubernetes CronJob
|
||||||
- It makes it easy to transfer data from cloud to any new deployment.
|
- It makes it easy to transfer data from cloud to any new deployment.
|
||||||
- They are just [site operations](site-operations.md) that can be manually pipelined as per need.
|
- They are just [site operations](site-operations.md) that can be manually pipelined as per need.
|
||||||
- Remember to restore encryption keys and other custom configuration from `site_config.json`.
|
- Remember to restore encryption keys and other custom configuration from `site_config.json`.
|
||||||
- Steps to move deployment:
|
- Steps to move deployment:
|
||||||
- [Take backup](site-operations.md#backup-sites)
|
- [Take backup](site-operations.md#backup-sites)
|
||||||
- [Push backup to cloud](site-operations.md#push-backup-to-s3-compatible-storage)
|
- [Push backup to cloud](site-operations.md#push-backup-to-s3-compatible-storage)
|
||||||
- Create new deployment type anywhere
|
- Create new deployment type anywhere
|
||||||
- [Restore backup from cloud](site-operations.md#restore-backups)
|
- [Restore backup from cloud](site-operations.md#restore-backups)
|
||||||
- [Restore `site_config.json` from cloud](site-operations.md#edit-configs)
|
- [Restore `site_config.json` from cloud](site-operations.md#edit-configs)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
redis-cache:
|
redis-cache:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
erpnext-nginx:
|
erpnext-nginx:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
frappe-nginx:
|
frappe-nginx:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user