aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--README.rst21
-rw-r--r--config/0x0.service18
-rw-r--r--config/cleanup_0x05
-rw-r--r--config/nginx.conf56
-rwxr-xr-xfhost.py160
-rw-r--r--requirements.txt33
7 files changed, 247 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index 64799da..ec6f452 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
__pycache__/
.py[cod]
+db.sqlite
+up/
+*.pyc
diff --git a/README.rst b/README.rst
index cf2ac7d..55f9fb2 100644
--- a/README.rst
+++ b/README.rst
@@ -2,7 +2,7 @@ The Null Pointer
================
This is a no-bullshit file hosting and URL shortening service that also runs
-`0x0.st <https://0x0.st>`_. Use with uWSGI.
+`envs.sh <https://envs.sh>`_. Use with uWSGI.
If you are running nginx, you should use the ``X-Accel-Redirect`` header.
To make it work, include this in your nginx config’s ``server`` block::
@@ -36,16 +36,23 @@ the following:
* ``ffmpegthumbnailer`` executable in ``$PATH``
+INSTALL
+-------
+::
+
+ apt update
+ apt install python3-pip nginx uwsgi uwsgi-plugin-python3 certbot
+ git clone https://github.com/envs-net/0x0.git /srv/0x0
+
+ cd /srv/0x0
+ pip3 install --user `cat requirements.txt`
+ ./fhost.py db upgrade
+
+
FAQ
---
Q:
- Will you ever add a web interface with HTML forms?
-A:
- No. This would without a doubt make it very popular and quickly exceed
- my hosting budget unless I started crippling it.
-
-Q:
What about file management? Will I be able to register an account at some
point?
A:
diff --git a/config/0x0.service b/config/0x0.service
new file mode 100644
index 0000000..ace57c0
--- /dev/null
+++ b/config/0x0.service
@@ -0,0 +1,18 @@
+# /etc/systemd/system/0x0.service
+[Unit]
+Description=null pointer
+After=network.target
+
+[Service]
+Type=simple
+User=0x0
+Group=0x0
+WorkingDirectory=/srv/0x0/
+ExecStart=/usr/bin/uwsgi_python3 --socket 127.0.0.1:3031 --wsgi-file fhost.py --callable app --processes 4 --threads 2 --master
+Restart=always
+RestartSec=5
+StartLimitInterval=60s
+StartLimitBurst=3
+
+[Install]
+WantedBy=default.target
diff --git a/config/cleanup_0x0 b/config/cleanup_0x0
new file mode 100644
index 0000000..2278eaa
--- /dev/null
+++ b/config/cleanup_0x0
@@ -0,0 +1,5 @@
+# /etc/cron.d/cleanup_0x0
+SHELL=/bin/sh
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+5 0 * * * root python3 /srv/0x0/cleanup.py >/dev/null 2>&1
diff --git a/config/nginx.conf b/config/nginx.conf
new file mode 100644
index 0000000..001f903
--- /dev/null
+++ b/config/nginx.conf
@@ -0,0 +1,56 @@
+server {
+ listen 80;
+# listen [::]:80;
+ server_name 0x0.envs.net;
+
+ access_log /var/log/nginx/0x0.envs.net-access.log;
+ error_log /var/log/nginx/0x0.envs.net-error.log;
+
+ location / {
+ return 307 https://$host$request_uri;
+ }
+
+ location /.well-known/acme-challenge/ {
+ alias /var/lib/letsencrypt/.well-known/acme-challenge/;
+ }
+}
+
+server {
+ listen 443 ssl http2;
+ server_name 0x0.envs.net;
+
+ ssl_certificate /etc/letsencrypt/live/0x0.envs.net/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/0x0.envs.net/privkey.pem;
+ ssl_protocols TLSv1.2;
+ ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
+ ssl_prefer_server_ciphers on;
+ ssl_session_cache shared:SSL:10m;
+ ssl_verify_depth 3;
+ ssl_dhparam /etc/ssl/certs/envs_dhparam.pem;
+
+ ssl_session_tickets off;
+ ssl_stapling on;
+ ssl_stapling_verify on;
+ ssl_trusted_certificate /etc/letsencrypt/live/0x0.envs.net/chain.pem;
+
+ add_header X-XSS-Protection "1; mode=block";
+ add_header X-Content-Type-Options nosniff;
+ # add_header X-Frame-Options "SAMEORIGIN";
+
+ access_log /var/log/nginx/0x0.envs.net-access.log;
+ error_log /var/log/nginx/0x0.envs.net-error.log;
+
+ root /srv/0x0;
+
+ location / {
+ include uwsgi_params;
+ uwsgi_param UWSGI_SCHEME $scheme;
+
+ # make sure this matches the port you're running uwsgi on
+ uwsgi_pass 127.0.0.1:3031;
+ }
+
+ location /up {
+ internal;
+ }
+}
diff --git a/fhost.py b/fhost.py
index 2814a96..5ad8938 100755
--- a/fhost.py
+++ b/fhost.py
@@ -37,7 +37,7 @@ app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite" # "postgresql://0x0@/0x0"
app.config["PREFERRED_URL_SCHEME"] = "https" # nginx users: make sure to have 'uwsgi_param UWSGI_SCHEME $scheme;' in your config
-app.config["MAX_CONTENT_LENGTH"] = 256 * 1024 * 1024
+app.config["MAX_CONTENT_LENGTH"] = 512 * 1024 * 1024
app.config["MAX_URL_LENGTH"] = 4096
app.config["FHOST_STORAGE_PATH"] = "up"
app.config["FHOST_USE_X_ACCEL_REDIRECT"] = True # expect nginx by default
@@ -151,6 +151,12 @@ def is_fhost_url(url):
return url.startswith(fhost_url()) or url.startswith(fhost_url("https"))
def shorten(url):
+ # handler to convert gopher links to HTTP(S) proxy
+ gopher = "gopher://"
+ length = len(gopher)
+ if url[:length] == gopher:
+ url = "https://gopher.envs.net/{}".format(url[length:])
+
if len(url) > app.config["MAX_URL_LENGTH"]:
abort(414)
@@ -252,6 +258,12 @@ def store_file(f, addr):
return sf.geturl()
def store_url(url, addr):
+ # handler to convert gopher links to HTTP(S) proxy
+ gopher = "gopher://"
+ length = len(gopher)
+ if url[:length] == gopher:
+ url = "https://gopher.envs.net/{}".format(url[length:])
+
if is_fhost_url(url):
return segfault(508)
@@ -337,14 +349,17 @@ def dump_urls(start=0):
@app.route("/", methods=["GET", "POST"])
def fhost():
if request.method == "POST":
- sf = None
+ out = None
if "file" in request.files:
- return store_file(request.files["file"], request.remote_addr)
+ out = store_file(request.files["file"], request.remote_addr)
elif "url" in request.form:
- return store_url(request.form["url"], request.remote_addr)
+ out = store_url(request.form["url"], request.remote_addr)
elif "shorten" in request.form:
- return shorten(request.form["shorten"])
+ out = shorten(request.form["shorten"])
+
+ if not out == None:
+ return Response(out, mimetype="text/plain")
abort(400)
else:
@@ -360,27 +375,93 @@ def fhost():
if maxsizehalf.is_integer():
maxsizehalf = int(maxsizehalf)
- return """<pre>
-THE NULL POINTER
-================
-
+ return """<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>{6}</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <meta name="description" content="envs.sh | Null Pointer" />
+ <link rel="stylesheet" href="https://envs.net/css/css_style.css" />
+ </head>
+ <body id="body" class="dark-mode">
+ <div class="clear" style="min-width: 1150px;">
+
+ <div id="main">
+<div class="block">
+<h1><em>envs.sh &#124; THE NULL POINTER</em></h1>
+<h2><em>file hosting and URL shortening service.</em></h2>
+<br />
+</div>
+
+<h2>USAGE</h2>
+<pre>
HTTP POST files here:
- curl -F'file=@yourfile.png' {0}
-You can also POST remote URLs:
- curl -F'url=http://example.com/image.jpg' {0}
-Or you can shorten URLs:
- curl -F'shorten=http://example.com/some/long/url' {0}
-
-File URLs are valid for at least 30 days and up to a year (see below).
-Shortened URLs do not expire.
-
-Maximum file size: {1}
-Not allowed: {5}
+ <code>curl -F'file=&#64;yourfile.png' {0}</code>
+post your text directly:
+ <code>echo "text here" | curl -F'file=@-;' {0}</code>
+you can also POST remote URLs:
+ <code>curl -F'url=https://example.com/image.jpg' {0}</code>
+or you can shorten URLs:
+ <code>curl -F'shorten=http://example.com/some/long/url' {0}</code>
+
+file URLs are valid for at least 30 days and up to a year (see below).
+shortened URLs do not expire.
+not allowed: {5}
+maximum file size: {1}
+</pre>
+<br />
+<h2>ACCEPTABLE USE POLICY</h2>
+<pre>
+please do not post any informations that
+may violate law (login/password lists, email lists, personal information).
-FILE RETENTION PERIOD
----------------------
+envs.sh is NOT a platform for:
+</pre>
+<br />
+<ul>
+ <li>child pornography</li>
+ <li>malware, including “potentially unwanted applications”</li>
+ <li>botnet command and control schemes involving this service</li>
+ <li>anything even remotely related to crypto currencies</li>
+ <li>hosting your backups</li>
+ <li>spamming the service with CI build artifacts</li>
+ <li>piracy</li>
+ <li>alt-right shitposting</li>
+</ul>
+<br />
+<h2>REQUIREMENTS</h2>
+<pre>
+there is only one thing you need to use this service - curl.
+curl is available on most platforms, including Windows, Mac OS X and Linux.
+
+if you run a server and like this site, clone it! centralization is bad.
+<small><a href="https://github.com/envs-net/0x0" target="_blank">https://github.com/envs-net/0x0</a></small>
+you can also support it financially via liberapay.
+<a href="https://en.liberapay.com/envs.net/donate" target="_blank" style="border-bottom-color: transparent;"><img src="https://img.shields.io/liberapay/receives/envs.net.svg?logo=liberapay" alt="img_shield_receives_via_liberapay"></a>
+</pre>
+<br />
+
+<h2>ALIAS</h2>
+<pre>
+to make your life easier, you can add aliases to your <code>.bash_aliases</code> on Linux
+and <code>.bash_profile</code> on Mac OS X. just remember to reset your terminal session after that.
+<code>0file&#40;&#41; &#123; curl -F"file=&#64;&#36;1" {0} ; &#125;
+0pb&#40;&#41; &#123; curl -F"file=@-;" {0} ; &#125;
+0url&#40;&#41; &#123; curl -F"url=&#36;1" {0} ; &#125;
+0short&#40;&#41; &#123; curl -F"shorten=&#36;1" {0} ; &#125;</code>
+
+now you can use:
+<code>0file "yourfile.png"
+&#35; or
+echo "text here" | 0pb</code>
+
+<em>if you want a nice wrapper, try <a href="https://git.envs.net/envs/pb">~tomasino's pb</a></em>
+</pre>
+<br />
+<h2>FILE RETENTION PERIOD</h2>
+<pre>
retention = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
days
@@ -404,20 +485,41 @@ retention = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
30 | ....................
0{2}{3}
{4}
+</pre>
+<br />
+
+<h2>ABUSE</h2>
+<pre>
+if you would like to request permanent deletion, please
+send an email to <a href="mailto:hostmaster@envs.net?subject=Abuse%200x0%20-%20envs.sh" target="_blank">hostmaster&#64;envs.net</a>.
+please allow up to 24 hours for a response.
+</pre>
+ </div>
-ABUSE
------
+<!-- UPLOAD -->
-If you would like to request permanent deletion, please contact lachs0r via
-IRC on Freenode, or send an email to lachs0r@(this domain).
+ <div id="sidebar">
+<div class="block">
+<h2>UPLOAD DIRECTLY</h2>
+<br />
+<form action="{0}" method="POST" enctype="multipart/form-data">
+<label>File:</label><br />
+<input class="form-control" type="file" name="file" style="width:250px;"><br />
+<input class="form-control" type="submit" value="Submit">
+</form>
+</div>
+ </div>
+
+ </div>
+
+ </body>
+</html>
-Please allow up to 24 hours for a response.
-</pre>
""".format(fhost_url(),
maxsize, str(maxsizehalf).rjust(27), str(maxsizenum).rjust(27),
maxsizeunit.rjust(54),
- ", ".join(app.config["FHOST_MIME_BLACKLIST"]))
+ ", ".join(app.config["FHOST_MIME_BLACKLIST"]),fhost_url().split("/",2)[2])
@app.route("/robots.txt")
def robots():
diff --git a/requirements.txt b/requirements.txt
index 7168db6..3004091 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,13 +1,20 @@
-alembic
-numpy
-SQLAlchemy
-tqdm
-Flask_SQLAlchemy
-Flask
-humanize
-requests
-flask_migrate
-flask_script
-python_magic
-short_url
-validators
+alembic==0.8.8
+click==6.6
+decorator==4.0.10
+Flask==0.11.1
+Flask-Migrate==2.0.0
+Flask-Script==2.0.5
+Flask-SQLAlchemy==2.1
+humanize==0.5.1
+itsdangerous==0.24
+Jinja2==2.8
+Mako==1.0.4
+MarkupSafe==0.23
+python-editor==1.0.1
+python-magic==0.4.12
+requests==2.11.1
+short-url==1.2.2
+six==1.10.0
+SQLAlchemy==1.1.3
+validators==0.11.0
+Werkzeug==0.11.11
bgstack15