centralize
This commit is contained in:
parent
9f1a934066
commit
0ffb5804db
26
.drone.yml
Normal file
26
.drone.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: Docker image build
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: config
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- echo -n "$VERSION,latest" > .tags
|
||||||
|
- sed -i -E "s/var_FRP_VERSION/$FRP_VERSION/" Dockerfile
|
||||||
|
- apk add openssl
|
||||||
|
- ./gen_uploads.sh
|
||||||
|
|
||||||
|
- name: build
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: quackerd/rainloop
|
30
Dockerfile
Normal file
30
Dockerfile
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
|
||||||
|
ENV VERSION=var_VERSION
|
||||||
|
ENV URL https://github.com/XTLS/Xray-core/releases/download/v${VERSION}/Xray-linux-64.zip
|
||||||
|
|
||||||
|
COPY ./run.sh /opt/run.sh
|
||||||
|
|
||||||
|
RUN set -xe && \
|
||||||
|
apk add --no-cache unzip wget nginx certbot openssl && \
|
||||||
|
wget ${URL} && \
|
||||||
|
mkdir -p /opt/xray && \
|
||||||
|
unzip Xray-linux-64.zip -d /opt/xray && \
|
||||||
|
rm Xray-linux-64.zip && \
|
||||||
|
mkdir -p /opt/config && \
|
||||||
|
mkdir -p /opt/config/logs && \
|
||||||
|
mkdir -p /opt/config/certs && \
|
||||||
|
mkdir -p /opt/config/logs/nginx && \
|
||||||
|
mkdir -p /opt/config/logs/xray && \
|
||||||
|
mkdir -p /opt/config/logs/crond && \
|
||||||
|
chmod +x /opt/run.sh && \
|
||||||
|
apk del unzip wget
|
||||||
|
|
||||||
|
COPY ./nginx.conf /opt/nginx.conf
|
||||||
|
COPY ./crontab /var/spool/cron/crontabs/root
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
CMD ["/opt/run.sh"]
|
19
LICENSE
19
LICENSE
@ -1,19 +0,0 @@
|
|||||||
MIT License Copyright (c) 2021 quackerd
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished
|
|
||||||
to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice (including the next
|
|
||||||
paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
|
||||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
||||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
118
client_conf.in
118
client_conf.in
@ -1,118 +0,0 @@
|
|||||||
{
|
|
||||||
"dns": {
|
|
||||||
"servers": [
|
|
||||||
"223.5.5.5",
|
|
||||||
"114.114.114.114",
|
|
||||||
{
|
|
||||||
"address": "8.8.8.8",
|
|
||||||
"port": 53,
|
|
||||||
"domains": [
|
|
||||||
"geosite:geolocation-!cn"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"address": "1.1.1.1",
|
|
||||||
"port": 53,
|
|
||||||
"domains": [
|
|
||||||
"geosite:geolocation-!cn"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"routing": {
|
|
||||||
"domainStrategy": "IPIfNonMatch",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"type": "field",
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"ip": [
|
|
||||||
"223.5.5.5",
|
|
||||||
"114.114.114.114"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "field",
|
|
||||||
"outboundTag": "proxy",
|
|
||||||
"ip": [
|
|
||||||
"8.8.8.8",
|
|
||||||
"1.1.1.1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "field",
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"ip": [
|
|
||||||
"geoip:cn",
|
|
||||||
"geoip:private"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "field",
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"domain": ["geosite:cn"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "field",
|
|
||||||
"outboundTag": "proxy",
|
|
||||||
"network": "udp,tcp"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"inbounds": [
|
|
||||||
{
|
|
||||||
"port": {{ port }},
|
|
||||||
"listen": "127.0.0.1",
|
|
||||||
"protocol": "socks",
|
|
||||||
"sniffing": {
|
|
||||||
"enabled": true,
|
|
||||||
"destOverride": ["http", "tls"]
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"auth": "noauth",
|
|
||||||
"udp": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"tag": "proxy",
|
|
||||||
"protocol": "vless",
|
|
||||||
"settings": {
|
|
||||||
"vnext": [
|
|
||||||
{
|
|
||||||
"address": "{{ subdomain }}.{{ domain }}",
|
|
||||||
"port": 443,
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": "{{ id }}",
|
|
||||||
"encryption": "none",
|
|
||||||
"level": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"streamSettings": {
|
|
||||||
"network": "tcp",
|
|
||||||
"security": "xtls",
|
|
||||||
"xtlsSettings": {
|
|
||||||
"serverName": "{{ subdomain }}.{{ domain }}",
|
|
||||||
"allowInsecure": false,
|
|
||||||
"alpn": ["h2","http/1.1"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"protocol": "freedom",
|
|
||||||
"settings": {},
|
|
||||||
"tag": "direct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"protocol": "blackhole",
|
|
||||||
"settings": {},
|
|
||||||
"tag": "block"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "{{ id }}",
|
|
||||||
"flow": "{{ flow }}",
|
|
||||||
"level": 0
|
|
||||||
}
|
|
43
config.yml
43
config.yml
@ -1,43 +0,0 @@
|
|||||||
server:
|
|
||||||
# domain: the domain name, e.g. google.com
|
|
||||||
domain: domain.tld
|
|
||||||
# subdomain: the subdomain name, e.g. write vps for vps.google.com. leave empty for naked domain.
|
|
||||||
subdomain: example
|
|
||||||
# loglevel: the log level of xray
|
|
||||||
# default: warning
|
|
||||||
loglevel:
|
|
||||||
# email: your email for the registered SSL cert. leave empty for a dummy email.
|
|
||||||
# default: dummy@dummy.org
|
|
||||||
email:
|
|
||||||
# uid/gid: the user/group to run the docker-compose stack.
|
|
||||||
# default: the current user
|
|
||||||
# comment: you can also manually set, e.g. uid: 1000 gid: 1000
|
|
||||||
uid:
|
|
||||||
gid:
|
|
||||||
# watchtower: enable watchtower docker image auto-update
|
|
||||||
# default: False
|
|
||||||
watchtower: False
|
|
||||||
|
|
||||||
clients:
|
|
||||||
# name: the name of the client, cannot be null
|
|
||||||
- name: example_user1
|
|
||||||
# id: the password(uuid) of each user, this can either be a string or an UUID. Please read the "comment" and "IMPORTANT" sections.
|
|
||||||
# default: auto-generated random string
|
|
||||||
# comment: for a managed environment we recommend hardcoding the id
|
|
||||||
# the generated id does NOT currently back-propagate to this file
|
|
||||||
# you WILL lose existing users if you run configure.py multiple times with blank ids as they will be regenerated with random ids
|
|
||||||
#
|
|
||||||
# ! IMPORTANT !: id DOES NOT have to be UUID, can be any string of length 1-30. This is supported by xray but not by some v2ray clients
|
|
||||||
# if the script detects that the id is not a valid UUID, it will also output the equivalent UUID of that string
|
|
||||||
id:
|
|
||||||
# flow: the flow parameter
|
|
||||||
# default: xtls-rprx-direct
|
|
||||||
flow:
|
|
||||||
# port: local socks5 proxy port on clients' machines
|
|
||||||
# default: 1080
|
|
||||||
port:
|
|
||||||
# you can also set each field manually like below:
|
|
||||||
# - name: example_user2
|
|
||||||
# id: example_passwd2
|
|
||||||
# flow: xtls-rprx-direct
|
|
||||||
# port: 6666
|
|
188
configure.py
188
configure.py
@ -1,188 +0,0 @@
|
|||||||
import getopt
|
|
||||||
import sys
|
|
||||||
import uuid
|
|
||||||
import pwd
|
|
||||||
import jinja2
|
|
||||||
import random
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
OUTPUT_DIR = "build"
|
|
||||||
CLIENT_OUTPUT_DIR = "clients"
|
|
||||||
DEFAULT_EMAIL = "dummy@dummy.org"
|
|
||||||
CONF_FILE = "config.yml"
|
|
||||||
SERVER_IN = "server.in"
|
|
||||||
SERVER_PATH = "xray"
|
|
||||||
SERVER_FN = "config.json"
|
|
||||||
NGINX_IN = "nginx.in"
|
|
||||||
NGINX_PATH = "nginx/nginx/site-confs"
|
|
||||||
NGINX_FN = "default"
|
|
||||||
CLIENT_OBJ_IN = "client_obj.in"
|
|
||||||
CLIENT_CONF_IN = "client_conf.in"
|
|
||||||
DOCKER_IN = "docker-compose.in"
|
|
||||||
WATCHTOWER_IN = "watchtower.in"
|
|
||||||
DEFAULT_WATCHTOWER_ENABLE = False
|
|
||||||
DEFAULT_CLIENT_PORT = 1080
|
|
||||||
DEFAULT_USER_FLOW = "xtls-rprx-direct"
|
|
||||||
DEFAULT_LOGLEVEL= "warning"
|
|
||||||
UUID_NAMESPACE = uuid.UUID('00000000-0000-0000-0000-000000000000')
|
|
||||||
|
|
||||||
def calc_uuid5(val):
|
|
||||||
return str(uuid.uuid5(UUID_NAMESPACE, val))
|
|
||||||
|
|
||||||
def is_valid_uuid(val):
|
|
||||||
try:
|
|
||||||
uuid.UUID(str(val))
|
|
||||||
return True
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def yaml_key_exists_else(mapping : [], name : str, other_val = None, nullable = True):
|
|
||||||
if (name in mapping) and (mapping[name] != None):
|
|
||||||
return mapping[name]
|
|
||||||
else:
|
|
||||||
if not nullable:
|
|
||||||
raise Exception("Key " + name + " must not be null.")
|
|
||||||
else:
|
|
||||||
return other_val
|
|
||||||
|
|
||||||
def random_string(stringLength=16):
|
|
||||||
letters = string.ascii_lowercase
|
|
||||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
|
||||||
|
|
||||||
class Client:
|
|
||||||
def __init__(self, conf_obj):
|
|
||||||
self.name = str(yaml_key_exists_else(conf_obj, 'name', nullable=False))
|
|
||||||
self.id = str(yaml_key_exists_else(conf_obj, 'id', other_val=random_string()))
|
|
||||||
self.flow = str(yaml_key_exists_else(conf_obj, 'flow', other_val=DEFAULT_USER_FLOW))
|
|
||||||
self.port = int(yaml_key_exists_else(conf_obj, 'port', other_val=DEFAULT_CLIENT_PORT))
|
|
||||||
|
|
||||||
def print(self, ident):
|
|
||||||
pre = ""
|
|
||||||
for i in range(ident):
|
|
||||||
pre += " "
|
|
||||||
|
|
||||||
print(pre + "{")
|
|
||||||
print(pre + " id: " + self.id)
|
|
||||||
print(pre + " uuid: " + (self.id if is_valid_uuid(self.id) else calc_uuid5(self.id)))
|
|
||||||
print(pre + " flow: " + self.flow)
|
|
||||||
print(pre + " port: " + str(self.port))
|
|
||||||
print(pre + "}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
def print(self):
|
|
||||||
print("Server configuration:")
|
|
||||||
print(" domain: " + self.domain)
|
|
||||||
print(" email: " + self.email)
|
|
||||||
print(" subdomain: " + self.subdomain)
|
|
||||||
print(" uid: " + str(self.uid))
|
|
||||||
print(" gid: " + str(self.gid))
|
|
||||||
print(" loglevel: " + self.loglevel)
|
|
||||||
print(" clients:")
|
|
||||||
for i in range(len(self.clients)):
|
|
||||||
self.clients[i].print(8)
|
|
||||||
|
|
||||||
def __init__(self, f):
|
|
||||||
conf = yaml.safe_load(f)
|
|
||||||
conf_srv = conf['server']
|
|
||||||
|
|
||||||
self.domain = str(yaml_key_exists_else(conf_srv, 'domain', nullable=False))
|
|
||||||
self.email = str(yaml_key_exists_else(conf_srv, 'email', other_val=DEFAULT_EMAIL))
|
|
||||||
self.subdomain = str(yaml_key_exists_else(conf_srv, 'subdomain', other_val=""))
|
|
||||||
self.subdomain_only = len(self.subdomain) > 0
|
|
||||||
self.uid = int(yaml_key_exists_else(conf_srv, 'uid', other_val=os.getuid()))
|
|
||||||
self.gid = int(yaml_key_exists_else(conf_srv, 'gid', other_val=os.getgid()))
|
|
||||||
self.loglevel = str(yaml_key_exists_else(conf_srv, 'loglevel', other_val=DEFAULT_LOGLEVEL))
|
|
||||||
self.watchtower = bool(yaml_key_exists_else(conf_srv, 'watchtower', other_val=DEFAULT_WATCHTOWER_ENABLE))
|
|
||||||
|
|
||||||
self.clients = []
|
|
||||||
conf_clients = conf['clients']
|
|
||||||
for i in range(len(conf_clients)):
|
|
||||||
self.clients.append(Client(conf_clients[i]))
|
|
||||||
|
|
||||||
def main():
|
|
||||||
with open(CONF_FILE, 'r') as f:
|
|
||||||
conf = Config(f)
|
|
||||||
conf.print()
|
|
||||||
|
|
||||||
template_dict = {}
|
|
||||||
template_dict['uid'] = conf.uid
|
|
||||||
template_dict['gid'] = conf.gid
|
|
||||||
template_dict['subdomain'] = conf.subdomain
|
|
||||||
template_dict['subdomain_only'] = str(conf.subdomain_only).lower()
|
|
||||||
template_dict['domain'] = conf.domain
|
|
||||||
template_dict['email'] = conf.email
|
|
||||||
template_dict['loglevel'] = conf.loglevel
|
|
||||||
|
|
||||||
if conf.watchtower:
|
|
||||||
with open(WATCHTOWER_IN, "r") as f:
|
|
||||||
template_dict['watchtower'] = f.read()
|
|
||||||
else:
|
|
||||||
template_dict['watchtower'] = ""
|
|
||||||
|
|
||||||
clients = ""
|
|
||||||
with open(CLIENT_OBJ_IN, "r") as f:
|
|
||||||
client_obj = f.read()
|
|
||||||
for i in range(len(conf.clients)):
|
|
||||||
if i > 0:
|
|
||||||
clients += ",\n"
|
|
||||||
clients += jinja2.Template(client_obj).render(id = conf.clients[i].id,
|
|
||||||
flow = conf.clients[i].flow)
|
|
||||||
template_dict['clients'] = clients
|
|
||||||
|
|
||||||
print("Generating files...")
|
|
||||||
|
|
||||||
# create output dir
|
|
||||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
|
||||||
|
|
||||||
# generate docker-compose.yml
|
|
||||||
path = os.path.join(OUTPUT_DIR, "docker-compose.yml")
|
|
||||||
with open(DOCKER_IN, "r") as f:
|
|
||||||
template = jinja2.Template(f.read())
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(template.render(template_dict))
|
|
||||||
|
|
||||||
# generate NGINX conf
|
|
||||||
with open(NGINX_IN, "r") as f:
|
|
||||||
template = jinja2.Template(f.read())
|
|
||||||
path = os.path.join(OUTPUT_DIR, NGINX_PATH)
|
|
||||||
os.makedirs(path, exist_ok=True)
|
|
||||||
path = os.path.join(path, NGINX_FN)
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(template.render(template_dict))
|
|
||||||
|
|
||||||
# generate xray conf
|
|
||||||
with open(SERVER_IN, "r") as f:
|
|
||||||
template = jinja2.Template(f.read())
|
|
||||||
path = os.path.join(OUTPUT_DIR, SERVER_PATH)
|
|
||||||
os.makedirs(path, exist_ok=True)
|
|
||||||
path = os.path.join(path, SERVER_FN)
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(template.render(template_dict))
|
|
||||||
|
|
||||||
# generate client confs
|
|
||||||
path = os.path.join(OUTPUT_DIR, CLIENT_OUTPUT_DIR)
|
|
||||||
os.makedirs(path, exist_ok=True)
|
|
||||||
with open(CLIENT_CONF_IN, "r") as f:
|
|
||||||
client_conf_temp = jinja2.Template(f.read())
|
|
||||||
for i in range(len(conf.clients)):
|
|
||||||
template_dict['id'] = conf.clients[i].id
|
|
||||||
template_dict['port'] = conf.clients[i].port
|
|
||||||
template_dict['flow'] = conf.clients[i].flow
|
|
||||||
epath = os.path.join(path, conf.clients[i].name)
|
|
||||||
os.makedirs(epath, exist_ok=True)
|
|
||||||
with open(os.path.join(epath, SERVER_FN), "w") as f:
|
|
||||||
f.write(client_conf_temp.render(template_dict))
|
|
||||||
|
|
||||||
# chown
|
|
||||||
os.chown(OUTPUT_DIR, conf.uid, conf.gid)
|
|
||||||
for dirpath, dirnames, filenames in os.walk(OUTPUT_DIR):
|
|
||||||
os.chown(dirpath, conf.uid, conf.gid)
|
|
||||||
for fname in filenames:
|
|
||||||
os.chown(os.path.join(dirpath, fname), conf.uid, conf.gid)
|
|
||||||
print("Please find the generated files in the build directory. To start the stack, run docker-compose up -d in the build directory.")
|
|
||||||
|
|
||||||
main()
|
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"log": {
|
"log": {
|
||||||
"loglevel": "{{ loglevel }}",
|
"loglevel": "debug",
|
||||||
"access": "/etc/xray/access.log",
|
"access": "/opt/config/xray/access.log",
|
||||||
"error": "/etc/xray/error.log"
|
"error": "/opt/config/xray/error.log"
|
||||||
},
|
},
|
||||||
"inbounds": [
|
"inbounds": [
|
||||||
{
|
{
|
||||||
@ -10,12 +10,15 @@
|
|||||||
"protocol": "vless",
|
"protocol": "vless",
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
{{ clients }}
|
{
|
||||||
|
"id": "zsy",
|
||||||
|
"flow": "xtls-rprx-direct"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"decryption": "none",
|
"decryption": "none",
|
||||||
"fallbacks": [
|
"fallbacks": [
|
||||||
{
|
{
|
||||||
"dest": "d2ray_nginx:80"
|
"dest": "localhost:80"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -26,8 +29,8 @@
|
|||||||
"alpn": ["http/1.1", "h2"],
|
"alpn": ["http/1.1", "h2"],
|
||||||
"certificates": [
|
"certificates": [
|
||||||
{
|
{
|
||||||
"certificateFile": "/le-etc/letsencrypt/live/{{ subdomain }}.{{ domain }}/fullchain.pem",
|
"certificateFile": "/etc/letsencrypt/live/concerto.quacker.net/fullchain.pem",
|
||||||
"keyFile": "/le-etc/letsencrypt/live/{{ subdomain }}.{{ domain }}/privkey.pem"
|
"keyFile": "/etc/letsencrypt/live/concerto.quacker.net/privkey.pem"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,60 +0,0 @@
|
|||||||
version: '3.0'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
br-d2ray:
|
|
||||||
external: false
|
|
||||||
driver: bridge
|
|
||||||
driver_opts:
|
|
||||||
com.docker.network.bridge.name: br-d2ray
|
|
||||||
enable_ipv6: false
|
|
||||||
ipam:
|
|
||||||
driver: default
|
|
||||||
config:
|
|
||||||
- subnet: 172.127.127.0/24
|
|
||||||
|
|
||||||
services:
|
|
||||||
d2ray_nginx:
|
|
||||||
container_name: d2ray_nginx
|
|
||||||
image: linuxserver/swag
|
|
||||||
restart: unless-stopped
|
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
networks:
|
|
||||||
- br-d2ray
|
|
||||||
environment:
|
|
||||||
- PUID={{ uid }}
|
|
||||||
- PGID={{ gid }}
|
|
||||||
- TZ=US/Eastern
|
|
||||||
- URL={{ domain }}
|
|
||||||
- SUBDOMAINS={{ subdomain }}
|
|
||||||
- VALIDATION=http
|
|
||||||
- EMAIL=dummy@dummy.com
|
|
||||||
- DHLEVEL=2048
|
|
||||||
- ONLY_SUBDOMAINS={{ subdomain_only }}
|
|
||||||
- STAGING=false
|
|
||||||
ports:
|
|
||||||
- 80:80
|
|
||||||
volumes:
|
|
||||||
- ./nginx:/config
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://{{ subdomain }}.{{ domain }}:80"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 3s
|
|
||||||
retries: 30
|
|
||||||
|
|
||||||
d2ray_xray:
|
|
||||||
container_name: d2ray_xray
|
|
||||||
image: teddysun/xray
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
d2ray_nginx:
|
|
||||||
condition: service_healthy
|
|
||||||
networks:
|
|
||||||
- br-d2ray
|
|
||||||
ports:
|
|
||||||
- 443:443
|
|
||||||
volumes:
|
|
||||||
- ./nginx/etc:/le-etc
|
|
||||||
- ./xray:/etc/xray
|
|
||||||
|
|
||||||
{{ watchtower }}
|
|
11
gen_upload.sh
Normal file
11
gen_upload.sh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set +e
|
||||||
|
|
||||||
|
mkdir -p ./uploads
|
||||||
|
|
||||||
|
for filename in ./confs/*; do
|
||||||
|
fname=$(basename $filename)
|
||||||
|
fhash=$(echo -n '$fname' | openssl dgst -md5 | sed -E 's/\(stdin\)= (.*)/\1/')
|
||||||
|
openssl aes-256-cbc -md sha512 -pbkdf2 -in $filename -out ./uploads/$fhash.conf -k "sergeygorbunov"
|
||||||
|
done
|
@ -1,17 +1,17 @@
|
|||||||
geo $external {
|
geo $external {
|
||||||
default 1;
|
default 1;
|
||||||
172.127.127.0/24 0;
|
localhost 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
listen 80 http http2 default_server;
|
||||||
server_name {{subdomain}}.{{domain}};
|
server_name {{subdomain}}.{{domain}};
|
||||||
|
|
||||||
if ($external) {
|
if ($external) {
|
||||||
return 301 https://$host$request_uri;
|
return 301 https://$host$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
root /config/www;
|
root /var/lib/nginx/html;
|
||||||
index index.html index.htm index.php;
|
index index.html;
|
||||||
}
|
}
|
||||||
|
|
55
run.sh
Normal file
55
run.sh
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set +e
|
||||||
|
|
||||||
|
BUCKET_NAME="config.quacker.net"
|
||||||
|
|
||||||
|
echo "===== Checking Environment Variables ====="
|
||||||
|
if [ -z "$FQDN" ]; then
|
||||||
|
echo "FQDN must be set"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "FQDN = $FQDN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SALT" ]; then
|
||||||
|
echo "SALT must be set"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "SALT = $SALT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$KEY" ]; then
|
||||||
|
echo "KEY must be set"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "KEY = $KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUCKET_HASH=$(echo -n "$BUCKET_NAME" | openssl dgst -md5 | sed -E 's/\(stdin\)= (.*)/\1/')
|
||||||
|
echo "BUCKET_HASH= $BUCKET_HASH"
|
||||||
|
|
||||||
|
echo "===== Setting Up Environment ======"
|
||||||
|
ln -s /opt/config/certs /etc/letsencrypt
|
||||||
|
|
||||||
|
echo "===== Checking Certificates ===="
|
||||||
|
if [ ! -d "/etc/letsencrypt/live/$FQDN" ]; then
|
||||||
|
echo "Generating new certificates..."
|
||||||
|
certbot certonly -n --standalone -m dummy@dummy.com --agree-tos --no-eff-email -d "$FQDN"
|
||||||
|
else
|
||||||
|
echo "Certificate exists. Checking renewal..."
|
||||||
|
certbot renew
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "===== Downloading configuration file ====="
|
||||||
|
hash=$(echo -n "$FQDN.$SALT" | openssl dgst -sha256 | sed -E 's/\(stdin\)= (.*)/\1/')
|
||||||
|
echo "Host hash is $hash"
|
||||||
|
wget http://$BUCKET_HASH.s3-website-us-west-1.amazonaws.com/config/$hash.conf -P /opt/
|
||||||
|
openssl aes-256-cbc -d -md sha512 -pbkdf2 -in /opt/$hash.conf -out /opt/$FQDN.conf -k $KEY
|
||||||
|
|
||||||
|
echo "===== Starting services ====="
|
||||||
|
crond -L /opt/config/logs/crond/log.txt
|
||||||
|
nginx -c /opt/nginx.conf
|
||||||
|
|
||||||
|
echo "===== Starting xray ====="
|
||||||
|
/opt/xray/xray -c /opt/$FQDN.conf
|
@ -1,8 +0,0 @@
|
|||||||
watchtower:
|
|
||||||
container_name: d2ray_watchtower
|
|
||||||
image: containrrr/watchtower
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- br-d2ray
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
Loading…
Reference in New Issue
Block a user