Compare commits

..

42 Commits

Author SHA1 Message Date
e6d65c9348 update readme 2026-04-21 19:58:52 +00:00
0a8d3b2426 stump tweaks 2026-04-20 19:27:09 +00:00
b8286725af remove kavita 2026-04-19 02:11:36 +00:00
9aaba3452e cleanup caddyfile comments 2026-04-16 06:25:07 +00:00
6f0df113c2 working book and caddy 2026-04-16 06:21:50 +00:00
0a8d754365 gitignore stumpdir 2026-04-13 22:28:38 +00:00
c34789a631 fix stump compose 2026-04-13 22:27:48 +00:00
49d08e8f42 Merge branch 'caddy' of https://gut.oily.dad/finn/site into caddy 2026-04-13 14:30:03 -07:00
fb5fc705dc add stump 2026-04-13 14:27:29 -07:00
f63ee28d2b pre fuse checkpoint 2026-04-13 18:08:52 +00:00
b780c043fa sshtun add rev tunnel keys 2026-04-13 00:50:58 -07:00
fa73ccbc90 Switch to Caddy 2026-04-12 18:09:30 -07:00
345d66b5c9 fix py3 back compat failure 2026-03-19 19:24:44 -07:00
b6ccb0c859 stop gitea regs 2026-03-19 21:18:01 +00:00
42a12d7ced also update example compose files 2026-01-04 08:03:22 +00:00
a329511464 set up admin-allowed registration 2026-01-04 08:01:10 +00:00
fc927eef63 add long staged emoji changes 2025-08-30 08:38:45 +00:00
7ed3b07ab4 Merge pull request 'Fixed typo.' (#7) from oily.mom/site:typo-fix into master
Reviewed-on: #7
Massive.
2025-08-30 04:46:38 +00:00
JustinOros
0f2ab58f00 Fixed typo. 2025-08-25 09:32:28 -07:00
950c9a6aea gitea ui tweaks 2025-01-02 02:22:57 +00:00
414c300b41 recenter gitea link 2024-09-05 20:24:47 -07:00
a5ac19a2a4 Merge pull request 'remove hard tabs oops' (#5) from tab_to_softtab into master
Reviewed-on: #5
2024-09-02 22:48:05 +00:00
78c0895418 disable gitea reg if link on tld 2024-09-02 07:47:47 +00:00
8cbe7eecd3 remove tabs from html 2024-09-02 07:22:23 +00:00
9090da987f gitea link in header 2024-09-02 00:04:58 -07:00
650e77210e move onion address to nginx header 2024-08-20 19:40:33 +00:00
16a45c495d restart always incomp with env switch 2024-08-10 06:30:54 -07:00
08ae04a154 ssh tunnel env switch and logging 2024-08-10 06:12:26 -07:00
78384a31fb Merge pull request 'initial working ssh entry' (#4) from ssh_in into master
Reviewed-on: #4
2024-08-10 02:18:05 +00:00
60280917c6 set default to prod 2024-08-10 02:08:35 +00:00
8f8c0c1401 fix composes 2024-08-09 18:58:40 -07:00
979adc3b13 initial working ssh entry 2024-08-09 18:47:22 -07:00
619ce9b0bd long username titles 2024-08-08 18:44:49 +00:00
bcec5d05c8 fix titles 2024-08-08 18:28:57 +00:00
71f8ff967c minor title fix profile 2024-08-08 11:25:28 -07:00
d61fd3bb2c fix post wrapping 2024-08-08 11:12:36 -07:00
234230c14a restorve dev values for env example checked safe 2024-08-08 10:14:31 -07:00
a22c1a4e1e minor color 2024-08-08 16:51:06 +00:00
51693a7860 add registration switch env composes 2024-08-08 16:14:28 +00:00
8f95303d11 add registration switch env 2024-08-08 16:10:43 +00:00
92b314623a appearance tweaks 2024-08-08 15:14:44 +00:00
1c6293fda3 alpine for tor 2024-08-08 04:42:12 -07:00
42 changed files with 741 additions and 465 deletions

9
.gitignore vendored
View File

@@ -1,7 +1,10 @@
gitea/ gitea
.env .env
pmb-pf/ pmb-pf
stump
kavita
venv venv
zapp.db zapp.db
db/bu db/bu
tor/hidden_service/ tor/hidden_service
sshtun/oilykey

View File

@@ -19,15 +19,18 @@ Install? PROBABLY NOT, this runs entirely in alpine and would be nice to isolate
### Admin general: ### Admin general:
usermod -aG docker finn - `usermod -aG docker finn`
- edit `/etc/systemd/journald.conf`
- set or append `SystemMaxUse=500M`
### Admin firewall: ### Admin firewall:
```
ufw default deny incoming ufw default deny incoming
ufw default allow outgoing ufw default allow outgoing
ufw allow "OpenSSH" ufw allow "OpenSSH"
ufw allow "WWW Full" ufw allow "WWW Full"
ufw enable ufw enable
```
### Admin dns: ### Admin dns:

View File

@@ -18,7 +18,7 @@ def send_email(subject, sender, recipients, text_body, html_body):
def send_password_reset_email(user): def send_password_reset_email(user):
token = user.get_reset_password_token() token = user.get_reset_password_token()
hostname = app.config['REAL_HOSTNAME'] hostname = app.config['REAL_HOSTNAME']
send_email('[Blog] Reset Password', send_email('reset oily password',
sender=app.config['ADMINS'][0], sender=app.config['ADMINS'][0],
recipients=[user.email], recipients=[user.email],
text_body=render_template('email/reset_password.txt', hostname=hostname, user=user, token=token), text_body=render_template('email/reset_password.txt', hostname=hostname, user=user, token=token),

View File

@@ -7,7 +7,7 @@ from app.models import User
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()]) username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Pasword', validators=[DataRequired()]) password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me') remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In') submit = SubmitField('Sign In')
@@ -51,7 +51,7 @@ class ResetPasswordRequestForm(FlaskForm):
submit = SubmitField('Request Password Reset') submit = SubmitField('Request Password Reset')
class PostForm(FlaskForm): class PostForm(FlaskForm):
post = TextAreaField('Post:', validators=[DataRequired(), Length(min=1, max=140)]) post = TextAreaField('Post', validators=[DataRequired(), Length(min=1, max=140)])
submit = SubmitField('Submit') submit = SubmitField('Submit')
class EmptyForm(FlaskForm): class EmptyForm(FlaskForm):

View File

@@ -66,7 +66,7 @@ class User(UserMixin, db.Model):
'#5000FF', '#5000FF',
'#FF0030'] '#FF0030']
background = '#151515' background = '#030303'
digest = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest() digest = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
basedir = os.path.abspath(os.path.dirname(__file__)) basedir = os.path.abspath(os.path.dirname(__file__))

View File

@@ -37,18 +37,19 @@ def index():
next_url = url_for('index', page=posts.next_num) if posts.has_next else None next_url = url_for('index', page=posts.next_num) if posts.has_next else None
prev_url = url_for('index', page=posts.prev_num) if posts.has_prev else None prev_url = url_for('index', page=posts.prev_num) if posts.has_prev else None
return render_template('index.html', title='Home', form=form, posts=posts.items, next_url=next_url, prev_url=prev_url) return render_template('index.html', title='oily home', form=form, posts=posts.items, next_url=next_url, prev_url=prev_url)
@app.route('/explore') @app.route('/explore')
@login_required @login_required
def explore(): def explore():
query = sa.select(Post).order_by(Post.timestamp.desc()) query = sa.select(Post).order_by(Post.timestamp.desc())
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
posts = db.paginate(query, page=page, per_page=app.config['POSTS_PER_PAGE'], error_out=False) ppp = app.config['POSTS_PER_PAGE'] * 2
posts = db.paginate(query, page=page, per_page=ppp, error_out=False)
next_url = url_for('explore', page=posts.next_num) if posts.has_next else None next_url = url_for('explore', page=posts.next_num) if posts.has_next else None
prev_url = url_for('explore', page=posts.prev_num) if posts.has_prev else None prev_url = url_for('explore', page=posts.prev_num) if posts.has_prev else None
return render_template('explore.html', title='Explore', posts=posts.items, next_url=next_url, prev_url=prev_url) return render_template('explore.html', title='oily explore', posts=posts.items, next_url=next_url, prev_url=prev_url)
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
def login(): def login():
@@ -65,7 +66,7 @@ def login():
if not next_page or urlsplit(next_page).netloc != '': if not next_page or urlsplit(next_page).netloc != '':
next_page = url_for('index') next_page = url_for('index')
return redirect(next_page) return redirect(next_page)
return render_template('login.html', title='Sign In', form=form) return render_template('login.html', title='oily sign in', form=form)
@app.route('/logout') @app.route('/logout')
def logout(): def logout():
@@ -76,6 +77,9 @@ def logout():
def register(): def register():
if current_user.is_authenticated: if current_user.is_authenticated:
return redirect(url_for('index')) return redirect(url_for('index'))
if not app.config['ALLOW_REGISTRATION'] == "true":
flash('Registration temporarily disabled.')
return redirect(url_for('login'))
form = RegistrationForm() form = RegistrationForm()
if form.validate_on_submit(): if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data) user = User(username=form.username.data, email=form.email.data)
@@ -85,7 +89,7 @@ def register():
#user.gen_avatar() #user.gen_avatar()
flash('User has been created.') flash('User has been created.')
return redirect(url_for('login')) return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form) return render_template('register.html', title='oily register', form=form)
@app.route('/reset_password/<token>', methods=['GET', 'POST']) @app.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token): def reset_password(token):
@@ -107,6 +111,7 @@ def reset_password(token):
@login_required @login_required
def user(username): def user(username):
user = db.first_or_404(sa.select(User).where(User.username == username)) user = db.first_or_404(sa.select(User).where(User.username == username))
shortname = (current_user.username[:10] + '...') if len(current_user.username) > 14 else current_user.username
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
query = user.posts.select().order_by(Post.timestamp.desc()) query = user.posts.select().order_by(Post.timestamp.desc())
posts = db.paginate(query, page=page, per_page=app.config['POSTS_PER_PAGE'], error_out=False) posts = db.paginate(query, page=page, per_page=app.config['POSTS_PER_PAGE'], error_out=False)
@@ -114,12 +119,13 @@ def user(username):
prev_url = url_for('user', username=user.username, page=posts.prev_num) if posts.has_prev else None prev_url = url_for('user', username=user.username, page=posts.prev_num) if posts.has_prev else None
form = EmptyForm() form = EmptyForm()
return render_template('user.html', user=user, posts=posts.items, next_url=next_url, prev_url=prev_url, form=form) return render_template('user.html', title='oily profile - '+shortname, user=user, posts=posts.items, next_url=next_url, prev_url=prev_url, form=form)
@app.route('/edit_profile', methods=['GET', 'POST']) @app.route('/edit_profile', methods=['GET', 'POST'])
@login_required @login_required
def edit_profile(): def edit_profile():
form = EditProfileForm(current_user.username) form = EditProfileForm(current_user.username)
shortname = (current_user.username[:10] + '...') if len(current_user.username) > 14 else current_user.username
if form.validate_on_submit(): if form.validate_on_submit():
current_user.username = form.username.data current_user.username = form.username.data
current_user.about_me = form.about_me.data current_user.about_me = form.about_me.data
@@ -129,7 +135,7 @@ def edit_profile():
elif request.method == 'GET': elif request.method == 'GET':
form.username.data = current_user.username form.username.data = current_user.username
form.about_me.data = current_user.about_me form.about_me.data = current_user.about_me
return render_template('edit_profile.html', title='Edit Profile', form=form) return render_template('edit_profile.html', title='oily edit profile - '+shortname, form=form)
@app.route('/follow/<username>', methods=['POST']) @app.route('/follow/<username>', methods=['POST'])
@login_required @login_required
@@ -180,6 +186,6 @@ def reset_password_request():
send_password_reset_email(user) send_password_reset_email(user)
flash('Password reset sent.') flash('Password reset sent.')
return redirect(url_for('login')) return redirect(url_for('login'))
return render_template('reset_password_request.html', title='Reset Password', form=form) return render_template('reset_password_request.html', title='oily password reset', form=form)

View File

@@ -0,0 +1 @@
eee

View File

@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<h1>File Not Found</h1> <h2>File Not Found</h1>
<p><a href="{{ url_for('index') }}">Back</a></p> <p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %} {% endblock %}

View File

@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<h1>An unexpected error has occurred.</h1> <h2>An unexpected error has occurred.</h1>
<p>Administrator has been notified.</p> <p>Administrator has been notified.</p>
<p><a href="{{ url_for('index') }}">Back</a></p> <p><a href="{{ url_for('index') }}">Back</a></p>

View File

@@ -1,13 +1,11 @@
<table>
<tr style="vertical-align: top;"> <tr style="vertical-align: top;">
<td style="vertical-align: middle; width: 60px;"> <td style="vertical-align: middle; width: 60px;">
<img style="vertical-align: middle; width: 40px;" src="data:image/png;base64,{{ post.author.gen_avatar(write_png=False) }}"> <img style="vertical-align: middle; width: 40px;" src="data:image/png;base64,{{ post.author.gen_avatar(write_png=False) }}">
</td> </td>
<td> <td style="word-break: break-word;">
<a href="{{ url_for('user', username=post.author.username) }}"> <a href="{{ url_for('user', username=post.author.username) }}">
{{ post.author.username }} {{ post.author.username }}
</a> says:<br> </a> says:<br>
{{ post.body }} {{ post.body }}
</td> </td>
</tr> </tr>
</table>

View File

@@ -0,0 +1,14 @@
<div>
{% if prev_url %}
<a class="button" href="{{ prev_url }}">Newer</a>
{% else %}
<a class="button" aria-disabled=true>Newer</a>
{% endif %}
{% if next_url %}
<a class="button" href="{{ next_url }}">Older</a>
{% else %}
<a class="button" aria-disabled=true>Older</a>
{% endif %}
</div>

View File

@@ -3,9 +3,9 @@
<head> <head>
<link rel="stylesheet" href="{{ url_for('static', filename='simple.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='simple.css') }}">
{% if title %} {% if title %}
<title>{{ title }} - blogpage</title> <title>{{ title }}</title>
{% else %} {% else %}
<title>Welcome to blog.</title> <title>oily page</title>
{% endif %} {% endif %}
</head> </head>
<body> <body>
@@ -19,10 +19,12 @@
<a {% block profilecurrent %}{% endblock %} href="{{ url_for('user', username=current_user.username) }}">profile</a> <a {% block profilecurrent %}{% endblock %} href="{{ url_for('user', username=current_user.username) }}">profile</a>
<a href="{{ url_for('logout') }}">logout</a> <a href="{{ url_for('logout') }}">logout</a>
{% endif %} {% endif %}
<a href="https://gut.oily.dad/explore/repos">
<img style="vertical-align: middle; horizontal-align: center; height: 22px" src="https://gut.oily.dad/assets/img/logo.svg" alt="Logo" aria-hidden="true">
</a>
</nav> </nav>
<h1>oily.dad</h1>
<h4>destroy me</h4> <h2>oily.dad</h2>
</header> </header>
<hr> <hr>
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1>Edit Profile</h1> <h2>Edit Profile</h1>
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<p> <p>

View File

@@ -3,7 +3,6 @@
{% block explorecurrent %}class="current"{% endblock %} {% block explorecurrent %}class="current"{% endblock %}
{% block content %} {% block content %}
<h1>Hello, {{ current_user.username }}!</h1>
{% if form %} {% if form %}
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
@@ -17,11 +16,13 @@
<p>{{ form.submit() }}</p> <p>{{ form.submit() }}</p>
</form> </form>
{% endif %} {% endif %}
<table>
{% for post in posts %} {% for post in posts %}
{% include '_post.html' %} {% include '_post.html' %}
{% endfor %} {% endfor %}
{% if prev_url %}<a href="{{ prev_url }}">Newer Posts</a>{% endif %} </table>
{% if next_url %}<a href="{{ next_url }}">Older Posts</a>{% endif %}
{% include '_postnav.html' %}
{% endblock %} {% endblock %}

View File

@@ -3,7 +3,6 @@
{% block indexcurrent %}class="current"{% endblock %} {% block indexcurrent %}class="current"{% endblock %}
{% block content %} {% block content %}
<h1>Hello, {{ current_user.username }}!</h1>
{% if form %} {% if form %}
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
@@ -17,11 +16,13 @@
<p>{{ form.submit() }}</p> <p>{{ form.submit() }}</p>
</form> </form>
{% endif %} {% endif %}
<table>
{% for post in posts %} {% for post in posts %}
{% include '_post.html' %} {% include '_post.html' %}
{% endfor %} {% endfor %}
{% if prev_url %}<a href="{{ prev_url }}">Newer Posts</a>{% endif %} </table>
{% if next_url %}<a href="{{ next_url }}">Older Posts</a>{% endif %}
{% include '_postnav.html' %}
{% endblock %} {% endblock %}

View File

@@ -3,7 +3,7 @@
{% block logincurrent %}class="current"{% endblock %} {% block logincurrent %}class="current"{% endblock %}
{% block content %} {% block content %}
<h1>Sign In</h1> <h2>Sign In</h1>
<form action="" method="post" novalidate> <form action="" method="post" novalidate>
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<p> <p>

View File

@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<h1>Register</h1> <h2>Register</h1>
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<p> <p>

View File

@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<h1>Reset Your Password</h1> <h2>Reset Your Password</h1>
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<p> <p>

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1>Reset Password</h1> <h2>Reset Password</h1>
<form action="" method="post"> <form action="" method="post">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<p> <p>

View File

@@ -3,19 +3,15 @@
{% block profilecurrent %}class="current"{% endblock %} {% block profilecurrent %}class="current"{% endblock %}
{% block content %} {% block content %}
<table> <article>
<tr valign="top"> <h2>
<td style="vertical-align: middle; text-align: center;"> <img style="vertical-align: middle; width: 60px;" src="data:image/png;base64,{{ user.gen_avatar(write_png=False) }}">
<img style="vertical-align: middle;" src="data:image/png;base64,{{ user.gen_avatar(write_png=False) }}"> User: {{ user.username }}
</td> </h2>
<td>
<h1>User: {{ user.username }}</h1>
<h1>CUdebug: {{ current_user }}</h1>
<h1>Udebug: {{ user }}</h1>
{% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %} {% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
{% if user.last_seen %}<p>Last activity: {{ user.last_seen }}</p>{% endif %} {% if user.last_seen %}<p>Last activity: {{ user.last_seen }}</p>{% endif %}
{% if user == current_user %} {% if user == current_user %}
<p><a href="{{ url_for('edit_profile') }}">Edit Profile</a></p> <p><a class="button" href="{{ url_for('edit_profile') }}">Edit Profile</a></p>
{% elif not current_user.is_following(user) %} {% elif not current_user.is_following(user) %}
<p> <p>
<form action="{{ url_for('follow', username=user.username) }}" method="post"> <form action="{{ url_for('follow', username=user.username) }}" method="post">
@@ -31,17 +27,16 @@
</form> </form>
</p> </p>
{% endif %} {% endif %}
</article>
</td>
</tr>
</table>
<hr> <hr>
<table>
{% for post in posts %} {% for post in posts %}
{% include '_post.html' %} {% include '_post.html' %}
{% endfor %} {% endfor %}
{% if prev_url %}<a href="{{ prev_url }}">Newer Posts</a>{% endif %} </table>
{% if next_url %}<a href="{{ next_url }}">Older Posts</a>{% endif %}
{% include '_postnav.html' %}
{% endblock %} {% endblock %}

View File

@@ -16,6 +16,7 @@ class Config:
ADMINS = [os.environ.get('DOTENV_ADMIN_EMAIL')] ADMINS = [os.environ.get('DOTENV_ADMIN_EMAIL')]
FROM_ADDRESS = os.environ.get('DOTENV_FROM_ADDRESS') FROM_ADDRESS = os.environ.get('DOTENV_FROM_ADDRESS')
REAL_HOSTNAME = os.environ.get('DOTENV_REAL_HOSTNAME') REAL_HOSTNAME = os.environ.get('DOTENV_REAL_HOSTNAME')
ALLOW_REGISTRATION = os.environ.get('DOTENV_ALLOW_REGISTRATION')
DC_LOGGING = True DC_LOGGING = True

View File

@@ -1,28 +1,28 @@
alembic==1.13.2 alembic
blinker==1.8.2 blinker
click==8.1.7 click
dnspython==2.6.1 dnspython
email_validator==2.2.0 email_validator
Flask==3.0.3 Flask
Flask-Login==0.6.3 Flask-Login
Flask-Mail==0.10.0 Flask-Mail
Flask-Migrate==4.0.7 Flask-Migrate
Flask-SQLAlchemy==3.1.1 Flask-SQLAlchemy
Flask-WTF==1.2.1 Flask-WTF
greenlet==3.0.3 greenlet
idna==3.7 idna
itsdangerous==2.2.0 itsdangerous
Jinja2==3.1.4 Jinja2
Mako==1.3.5 Mako
mariadb==1.1.10 mariadb
MarkupSafe==2.1.5 MarkupSafe
packaging==24.1 packaging
pillow==10.4.0 pillow
pydenticon==0.3.1 pydenticon
PyJWT==2.9.0 PyJWT
python-dotenv==1.0.1 python-dotenv
SQLAlchemy==2.0.31 SQLAlchemy
typing_extensions==4.12.2 typing_extensions
uWSGI==2.0.26 uWSGI
Werkzeug==3.0.3 Werkzeug
WTForms==3.1.2 WTForms

View File

@@ -0,0 +1,28 @@
alembic==1.13.2
blinker==1.8.2
click==8.1.7
dnspython==2.6.1
email_validator==2.2.0
Flask==3.0.3
Flask-Login==0.6.3
Flask-Mail==0.10.0
Flask-Migrate==4.0.7
Flask-SQLAlchemy==3.1.1
Flask-WTF==1.2.1
greenlet==3.0.3
idna==3.7
itsdangerous==2.2.0
Jinja2==3.1.4
Mako==1.3.5
mariadb==1.1.10
MarkupSafe==2.1.5
packaging==24.1
pillow==10.4.0
pydenticon==0.3.1
PyJWT==2.9.0
python-dotenv==1.0.1
SQLAlchemy==2.0.31
typing_extensions==4.12.2
uWSGI==2.0.28
Werkzeug==3.0.3
WTForms==3.1.2

View File

@@ -31,7 +31,7 @@ services:
#tty: true #tty: true
restart: always restart: always
# Comment following line to use flask (1worker, dev), uncomment to use uwsgi (wsgi) # Comment following line to use flask (1worker, dev), uncomment to use uwsgi (wsgi)
command: ["uwsgi", "--http", "0.0.0.0:8000", "--master", "-p", "4", "-w", "microblog:app"] #command: ["uwsgi", "--http", "0.0.0.0:8000", "--master", "-p", "4", "--buffer-size", "16384", "--limit-as", "2048", "-w", "microblog:app"]
container_name: backend container_name: backend
environment: environment:
- MYSQL_USER=flasku - MYSQL_USER=flasku
@@ -44,6 +44,7 @@ services:
- DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM} - DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM}
- DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE} - DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE}
- DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME} - DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME}
- DOTENV_ALLOW_REGISTRATION=${ALLOW_REGISTRATION}
#ports: #ports:
# - 8000:8000 # - 8000:8000
expose: expose:
@@ -74,10 +75,13 @@ services:
- GITEA__mailer__PROTOCOL=smtp - GITEA__mailer__PROTOCOL=smtp
- GITEA__mailer__SMTP_ADDR=pmb - GITEA__mailer__SMTP_ADDR=pmb
- GITEA__mailer__SMTP_PORT=25 - GITEA__mailer__SMTP_PORT=25
- GITEA__service__REGISTER_EMAIL_CONFIRM=true - GITEA__service__REGISTER_EMAIL_CONFIRM=false
- GITEA__service__REGISTER_MANUAL_CONFIRM=true
- GITEA__service__ENABLE_NOTIFY_MAIL=true - GITEA__service__ENABLE_NOTIFY_MAIL=true
- GITEA__server__LANDING_PAGE=explore
- GITEA__ui__REACTIONS="+1, -1, fu, heart, laugh, confused, hooray, eyes, gun, boom, poop, kiss, rocket, bomb, chart_with_downwards_trend, eggplant"
# To disable new users after setup: # To disable new users after setup:
#- GITEA__service__DISABLE_REGISTRATION=false - GITEA__service__DISABLE_REGISTRATION=true
networks: networks:
- backnet - backnet
- frontnet - frontnet
@@ -99,8 +103,8 @@ services:
- /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro - /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro
- /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro - /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro
ports: ports:
- 80:80 - "80:80"
- 443:443 - "443:443"
depends_on: depends_on:
- backend - backend
networks: networks:
@@ -134,6 +138,48 @@ services:
networks: networks:
- backnet - backnet
stump:
image: aaronleopold/stump
#image: aaronleopold/stump:nightly
container_name: stump
# Replace my paths (prior to the colons) with your own
volumes:
- ./stump:/config
#- /mnt/hub/rocky-remote/st/rockybookshare/:/rocky-remote
#- /mnt/hub/rocky-remote/st/briebookshare/:/rocky-redundant
#- /mnt/hub/brie-remote/st/bookshare:/brie-remote
- /home/armbian/mnt/gouda/st/data/:/bookshare/gouda
- /home/armbian/mnt/rocky/st/data/:/bookshare/rocky
#ports:
# - 10801:10801
environment:
- PUID=1000
- PGID=1000
- STUMP_ENABLE_UPLOAD=true
- ENABLE_KOREADER_SYNC=true
- ENABLE_OPDS_PROGRESSION=true
- STUMP_MAX_SCANNER_CONCURRENCY=2
- STUMP_MAX_THUMBNAIL_CONCURRENCY=1
- STUMP_VERBOSITY=1
restart: unless-stopped
networks:
- frontnet
- backnet
sshtun:
build:
context: sshtun
dockerfile: Dockerfile
restart: on-failure
environment:
- USE_TUN=${USE_TUN}
ports:
- "22222:22"
expose:
- "11112"
networks:
- frontnet
volumes: volumes:
db-data: db-data:
pmb-root: pmb-root:

View File

@@ -44,6 +44,7 @@ services:
- DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM} - DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM}
- DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE} - DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE}
- DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME} - DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME}
- DOTENV_ALLOW_REGISTRATION=${ALLOW_REGISTRATION}
#ports: #ports:
# - 8000:8000 # - 8000:8000
expose: expose:
@@ -74,10 +75,13 @@ services:
- GITEA__mailer__PROTOCOL=smtp - GITEA__mailer__PROTOCOL=smtp
- GITEA__mailer__SMTP_ADDR=pmb - GITEA__mailer__SMTP_ADDR=pmb
- GITEA__mailer__SMTP_PORT=25 - GITEA__mailer__SMTP_PORT=25
- GITEA__service__REGISTER_EMAIL_CONFIRM=true - GITEA__service__REGISTER_EMAIL_CONFIRM=false
- GITEA__service__REGISTER_MANUAL_CONFIRM=true
- GITEA__service__ENABLE_NOTIFY_MAIL=true - GITEA__service__ENABLE_NOTIFY_MAIL=true
- GITEA__server__LANDING_PAGE=explore
- GITEA__ui__REACTIONS="+1, -1, fu, heart, laugh, confused, hooray, eyes, gun, boom, poop, kiss, rocket, bomb, chart_with_downwards_trend, eggplant"
# To disable new users after setup: # To disable new users after setup:
#- GITEA__service__DISABLE_REGISTRATION=false - GITEA__service__DISABLE_REGISTRATION=false
networks: networks:
- backnet - backnet
- frontnet - frontnet
@@ -99,8 +103,8 @@ services:
# - /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro # - /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro
# - /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro # - /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro
ports: ports:
- 80:80 - "80:80"
- 443:443 - "443:443"
depends_on: depends_on:
- backend - backend
networks: networks:
@@ -117,12 +121,12 @@ services:
- frontnet - frontnet
pmb: pmb:
build: #build:
args: # args:
GPG_PP: $BUILD_GPG_PP # GPG_PP: $BUILD_GPG_PP
context: pmb-pf # context: pmb-pf
dockerfile: Dockerfile # dockerfile: Dockerfile
#image: site_pmb:latest image: site_pmb:latest
expose: expose:
- "25" - "25"
env_file: env_file:
@@ -134,6 +138,20 @@ services:
networks: networks:
- backnet - backnet
sshtun:
build:
context: sshtun
dockerfile: Dockerfile
restart: on-failure
environment:
- USE_TUN=${USE_TUN}
ports:
- "22222:22"
expose:
- "11112"
networks:
- frontnet
volumes: volumes:
db-data: db-data:
pmb-root: pmb-root:

View File

@@ -44,6 +44,7 @@ services:
- DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM} - DOTENV_FROM_ADDRESS=${FLASK_MAIL_FROM}
- DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE} - DOTENV_JWT_PHRASE=${FLASK_JWT_PHRASE}
- DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME} - DOTENV_REAL_HOSTNAME=${FLASK_REAL_HOSTNAME}
- DOTENV_ALLOW_REGISTRATION=${ALLOW_REGISTRATION}
#ports: #ports:
# - 8000:8000 # - 8000:8000
expose: expose:
@@ -74,10 +75,13 @@ services:
- GITEA__mailer__PROTOCOL=smtp - GITEA__mailer__PROTOCOL=smtp
- GITEA__mailer__SMTP_ADDR=pmb - GITEA__mailer__SMTP_ADDR=pmb
- GITEA__mailer__SMTP_PORT=25 - GITEA__mailer__SMTP_PORT=25
- GITEA__service__REGISTER_EMAIL_CONFIRM=true - GITEA__service__REGISTER_EMAIL_CONFIRM=false
- GITEA__service__REGISTER_MANUAL_CONFIRM=true
- GITEA__service__ENABLE_NOTIFY_MAIL=true - GITEA__service__ENABLE_NOTIFY_MAIL=true
- GITEA__server__LANDING_PAGE=explore
- GITEA__ui__REACTIONS="+1, -1, fu, heart, laugh, confused, hooray, eyes, gun, boom, poop, kiss, rocket, bomb, chart_with_downwards_trend, eggplant"
# To disable new users after setup: # To disable new users after setup:
#- GITEA__service__DISABLE_REGISTRATION=false - GITEA__service__DISABLE_REGISTRATION=false
networks: networks:
- backnet - backnet
- frontnet - frontnet
@@ -99,8 +103,8 @@ services:
- /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro - /home/finn/d/cert/var/lib/letsencrypt:/var/lib/letsencrypt:ro
- /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro - /home/finn/d/cert/etc/letsencrypt:/etc/letsencrypt:ro
ports: ports:
- 80:80 - "80:80"
- 443:443 - "443:443"
depends_on: depends_on:
- backend - backend
networks: networks:
@@ -117,12 +121,12 @@ services:
- frontnet - frontnet
pmb: pmb:
build: #build:
args: # args:
GPG_PP: $BUILD_GPG_PP # GPG_PP: $BUILD_GPG_PP
context: pmb-pf # context: pmb-pf
dockerfile: Dockerfile # dockerfile: Dockerfile
#image: site_pmb:latest image: site_pmb:latest
expose: expose:
- "25" - "25"
env_file: env_file:
@@ -134,6 +138,20 @@ services:
networks: networks:
- backnet - backnet
sshtun:
build:
context: sshtun
dockerfile: Dockerfile
restart: on-failure
environment:
- USE_TUN=${USE_TUN}
ports:
- "22222:22"
expose:
- "11112"
networks:
- frontnet
volumes: volumes:
db-data: db-data:
pmb-root: pmb-root:

32
dotenv
View File

@@ -1,30 +1,34 @@
# Example .env file # Example .env file
DOTENV_MYSQL_ROOT_PASSWORD_OLD=rootp DOTENV_MYSQL_ROOT_PASSWORD_OLD="rootp"
DOTENV_MYSQL_ROOT_PASSWORD=rootp DOTENV_MYSQL_ROOT_PASSWORD="rootp"
DOTENV_MYSQL_GITEA_PASSWORD=giteap DOTENV_MYSQL_GITEA_PASSWORD="giteap"
DOTENV_MYSQL_FLASK_PASSWORD=flaskp DOTENV_MYSQL_FLASK_PASSWORD="flaskp"
GITEA_MAIL_FROM="git@e.e" GITEA_MAIL_FROM="git@aaa"
# Build ARG GPG_PP. May still need to be empty to avoid breakage. # Build ARG GPG_PP. May still need to be empty to avoid breakage.
BUILD_GPG_PP= BUILD_GPG_PP=
# Tor: # Tor:
# true/false # true/false:
USE_TOR=false USE_TOR=false
# SSH Tun:
# true/false:
USE_TUN=false
# Backend: # Backend:
FLASK_SECRET_KEY="flaskkey" FLASK_SECRET_KEY="flaskkey"
# Inconsequential token: minimal inconvenience if exposed # Inconsequential token: minimal inconvenience if exposed
FLASK_TOKEN_I=dti FLASK_TOKEN_I="dti"
# Consequential token: protect # Consequential token: protect
FLASK_TOKEN_C=dtc FLASK_TOKEN_C="dtc"
# true/false:
FLASK_MAIL_FROM="git@e.e" ALLOW_REGISTRATION=true
FLASK_MAIL_FROM="git@aaa"
# admin email must be valid send from with mail subsystem # admin email must be valid send from with mail subsystem
FLASK_ADMIN_EMAIL="git@e.e" FLASK_ADMIN_EMAIL="git@aaa"
FLASK_JWT_PHRASE="tphrase" FLASK_JWT_PHRASE="jwtphrase"
FLASK_REAL_HOSTNAME="localhost" FLASK_REAL_HOSTNAME="localhost"

5
ls_rclone.sh Normal file
View File

@@ -0,0 +1,5 @@
rclone ls :sftp: \
--sftp-host=localhost \
--sftp-port=11111 \
--sftp-user=armbian \
--sftp-key-file=/home/armbian/.ssh/armbian-brie-202604

72
proxy/Caddyfile Normal file
View File

@@ -0,0 +1,72 @@
# Global options
{
# Disable auto HTTPS since we're using existing certificates
auto_https off
}
# HTTP to HTTPS redirect
:80 {
redir https://{host}{uri} permanent
}
# Main domain - oily.dad and www.oily.dad
oily.dad, www.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Onion-Location header
header Onion-Location http://oilydada7ckiseinkbeathsefwgkvjrce743xy7x7iiybkuxh4vheead.onion{path}
# Reverse proxy to backend
reverse_proxy http://backend:8000 {
# Preserve original host header
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Gitea - gut.oily.dad
gut.oily.dad {
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Gitea
reverse_proxy http://gitea:3000 {
# WebSocket support for Gitea
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
# Preserve original headers
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Stump - stump.oily.dad
stump.oily.dad {
# kavita supports gzip seems to work with stump
encode gzip
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Stump
reverse_proxy http://stump:10801 {
#reverse_proxy http://kavita:5000 {
# WebSocket support for Stump (if needed)
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
# Preserve original headers
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}

65
proxy/Caddyfile.maybeno Normal file
View File

@@ -0,0 +1,65 @@
# Global options
{
# Disable auto HTTPS since we're using existing certificates
auto_https off
}
# HTTP to HTTPS redirect
:80 {
redir https://{host}{uri} permanent
}
# Main domain - oily.dad and www.oily.dad
oily.dad, www.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Onion-Location header
header Onion-Location http://oilydada7ckiseinkbeathsefwgkvjrce743xy7x7iiybkuxh4vheead.onion{path}
# Reverse proxy to backend
reverse_proxy http://backend:8000 {
# Preserve original host header
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Gitea - gut.oily.dad
gut.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Gitea
reverse_proxy http://gitea:3000 {
# WebSocket support for Gitea
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
# Preserve original headers
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Stump (comics/books) - book.oily.dad
book.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Stump
#reverse_proxy http://stump:10801 {
reverse_proxy http://kavita:5000
}

74
proxy/Caddyfile.old Normal file
View File

@@ -0,0 +1,74 @@
# Global options
{
# Disable auto HTTPS since we're using existing certificates
auto_https off
}
# HTTP to HTTPS redirect
:80 {
redir https://{host}{uri} permanent
}
# Main domain - oily.dad and www.oily.dad
oily.dad, www.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Onion-Location header
header Onion-Location http://oilydada7ckiseinkbeathsefwgkvjrce743xy7x7iiybkuxh4vheead.onion{path}
# Reverse proxy to backend
reverse_proxy http://backend:8000 {
# Preserve original host header
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Gitea - gut.oily.dad
gut.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Gitea
reverse_proxy http://gitea:3000 {
# WebSocket support for Gitea
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
# Preserve original headers
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}
# Subdomain for Stump (comics/books) - book.oily.dad
book.oily.dad {
# Root directory (not strictly needed for reverse proxy)
root * /var/www/html
# Use existing SSL certificates
tls /etc/letsencrypt/live/oily.dad/fullchain.pem /etc/letsencrypt/live/oily.dad/privkey.pem
# Reverse proxy to Stump
#reverse_proxy http://stump:10801 {
reverse_proxy http://kavita:5000 {
# WebSocket support for Stump (if needed)
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
# Preserve original headers
header_up Host {host}
header_up X-Real-IP {remote}
# X-Forwarded-For and X-Forwarded-Proto are set automatically by Caddy
}
}

View File

@@ -1,2 +1,10 @@
FROM nginx:alpine FROM caddy:alpine
COPY conf /etc/nginx/conf.d/default.conf
# Copy Caddyfile configuration
COPY Caddyfile /etc/caddy/Caddyfile
# Create directory for www root
RUN mkdir -p /var/www/html
# Caddy runs as non-root user by default
# Ports 80 and 443 are exposed by the base image

View File

@@ -1,12 +0,0 @@
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend:8000;
}
location /gutty{
proxy_pass http://gitea:3000;
}
}

View File

@@ -1,52 +0,0 @@
#server {
# listen 80;
# server_name localhost;
# location / {
# proxy_pass http://backend:8000;
# }
# always redirect to https
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
# use the certificates
ssl_certificate /etc/letsencrypt/live/oily.dad/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/oily.dad/privkey.pem;
server_name oily.dad www.oily.dad;
root /var/www/html;
index index.php index.html index.htm;
location / {
proxy_pass http://backend:8000/;
}
}
server {
listen 443 ssl http2;
# use the certificates
ssl_certificate /etc/letsencrypt/live/oily.dad/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/oily.dad/privkey.pem;
server_name gut.oily.dad;
root /var/www/html;
index index.php index.html index.htm;
location / {
client_max_body_size 512M;
#proxy_pass http://localhost:3000;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
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_set_header X-Forwarded-Proto $scheme;
proxy_pass http://gitea:3000/;
}
}

View File

@@ -1,17 +0,0 @@
server {
listen 80;
server_name localhost;
location / {
client_max_body_size 512M;
#proxy_pass http://localhost:3000;
proxy_pass http://gitea:3000;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
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_set_header X-Forwarded-Proto $scheme;
}
}

View File

@@ -1,52 +0,0 @@
#server {
# listen 80;
# server_name localhost;
# location / {
# proxy_pass http://backend:8000;
# }
# always redirect to https
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
# use the certificates
ssl_certificate /etc/letsencrypt/live/oily.dad/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/oily.dad/privkey.pem;
server_name oily.dad www.oily.dad;
root /var/www/html;
index index.php index.html index.htm;
location / {
proxy_pass http://backend:8000/;
}
}
server {
listen 443 ssl http2;
# use the certificates
ssl_certificate /etc/letsencrypt/live/oily.dad/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/oily.dad/privkey.pem;
server_name gut.oily.dad;
root /var/www/html;
index index.php index.html index.htm;
location / {
client_max_body_size 512M;
#proxy_pass http://localhost:3000;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
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_set_header X-Forwarded-Proto $scheme;
proxy_pass http://gitea:3000/;
}
}

23
sshtun/Dockerfile Normal file
View File

@@ -0,0 +1,23 @@
FROM debian:13-slim
RUN apt update
RUN apt install -y \
openssh-server \
socat
RUN adduser --disabled-password --gecos "" armbian
# ssh:
RUN mkdir /home/armbian/.ssh
# only one pubkey -- wildcard just to conceal filename
COPY ./oilykey/*.pub /home/armbian/.ssh/authorized_keys
COPY ./oilykey/* /home/armbian/.ssh/
RUN chown -R armbian:armbian /home/armbian/.ssh/
RUN chmod 600 /home/armbian/.ssh/*
#RUN mkdir /var/run/sshd
RUN echo "PermitRootLogin no" >> /etc/ssh/sshd_config
RUN echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
COPY ./entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]

14
sshtun/entrypoint.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
# Container goal: egress
# first: physical_box$ autossh -N -R 11111:localhost:11434 -i sshtun/oilykey/<SOMEKEY> -p 22222 <rem_vps_url>
# will forward rem_c_port:physical_box:physical_box_port ...some args... rem_vps_p rem_vps_url
# then: frontnet_c$ curl sshtun.frontnet:11112 --> physical_box:11434
if $USE_TUN ; then
echo "@@@@@@@@@@ SSH TUNNEL ENABLED BY ENV"
nohup socat TCP-LISTEN:11112,fork TCP:localhost:11111 &
/usr/sbin/sshd -De
else
echo "@@@@@@@@@@ SSH TUNNEL DISABLED BY ENV"
fi

8
sshtun/manual_rclone.sh Executable file
View File

@@ -0,0 +1,8 @@
rclone mount :sftp: /armbian/briemount \
--sftp-host=localhost \
--sftp-port=11111 \
--sftp-user=armbian \
--sftp-key-file=/home/armbian/.ssh/armbian-brie-202604 \
--vfs-cache-mode off \
--allow-other \
--daemon

View File

@@ -1,8 +1,8 @@
FROM debian:12-slim FROM alpine
RUN adduser --disabled-password --gecos "" tor RUN adduser --disabled-password --gecos "" tor
RUN apt update && apt install -y tor curl RUN apk update && apk add tor
COPY hidden_service /hidden_service COPY hidden_service /hidden_service
COPY torrc /etc/tor/torrc COPY torrc /etc/tor/torrc
@@ -10,6 +10,7 @@ COPY entrypoint.sh /
RUN chown -R tor /etc/tor RUN chown -R tor /etc/tor
RUN chown -R tor /hidden_service RUN chown -R tor /hidden_service
RUN chown -R tor /entrypoint.sh
RUN chmod -R go-rwx /etc/tor RUN chmod -R go-rwx /etc/tor
RUN chmod -R go-rwx /hidden_service RUN chmod -R go-rwx /hidden_service

View File

@@ -1,8 +1,8 @@
#!/bin/bash #!/bin/ash
if $USE_TOR ; then if $USE_TOR ; then
echo "@@@@@@@@@@ TOR ENABLED BY ENV" echo "@@@@@@@@@@ TOR ENABLED BY ENV"
exec tor exec /usr/bin/tor
else else
echo "@@@@@@@@@@ TOR DISABLED BY ENV" echo "@@@@@@@@@@ TOR DISABLED BY ENV"
fi fi