├── data └── .gitkeep ├── .dockerignore ├── config.pl.sample ├── docker-compose.yml ├── Dockerfile ├── README.md ├── restore.yml ├── files.service ├── files.nginx ├── backup.yml └── app.pl /data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | data 2 | -------------------------------------------------------------------------------- /config.pl.sample: -------------------------------------------------------------------------------- 1 | :- module(config,[config/2]). 2 | 3 | config(user,"123456"). 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | app: 4 | restart: always 5 | build: . 6 | volumes: 7 | - ./data:/opt/files-prolog/data 8 | ports: 9 | - "2345:2345" 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM arm32v7/swipl:8.2.3 2 | 3 | WORKDIR /opt/files-prolog 4 | 5 | COPY app.pl ./ 6 | COPY config.pl ./ 7 | 8 | RUN useradd prolog 9 | 10 | USER prolog 11 | CMD ["swipl","app.pl"] 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Files 2 | 3 | Static files go in data folder 4 | 5 | ``` 6 | docker-compose up 7 | ``` 8 | 9 | ## Backup 10 | 11 | ``` 12 | ansible-playbook backup.yml -i 192.168.0.158, --ask-pass 13 | ``` 14 | -------------------------------------------------------------------------------- /restore.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | remote_user: pi 3 | become_method: sudo 4 | name: "Restore Files" 5 | tasks: 6 | - name: Unpack backup 7 | unarchive: 8 | src: backups/files.tar.xz 9 | dest: /home/pi 10 | -------------------------------------------------------------------------------- /files.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Files 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | WorkingDirectory=/home/pi/files-prolog 8 | ExecStart=/usr/local/bin/docker-compose up 9 | ExecStop=/usr/local/bin/docker-compose down 10 | TimeoutStartSec=0 11 | Restart=on-failure 12 | StartLimitIntervalSec=60 13 | StartLimitBurst=3 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /files.nginx: -------------------------------------------------------------------------------- 1 | upstream files.adrianistan.eu { 2 | server 192.168.0.158:2345; 3 | } 4 | 5 | server { 6 | listen 80; 7 | listen 443 ssl http2; 8 | server_name files.adrianistan.eu; 9 | 10 | ssl_certificate /etc/letsencrypt/live/files.adrianistan.eu/fullchain.pem; 11 | ssl_certificate_key /etc/letsencrypt/live/files.adrianistan.eu/privkey.pem; 12 | 13 | location / { 14 | proxy_set_header Host $http_host; 15 | 16 | proxy_pass http://files.adrianistan.eu; 17 | proxy_redirect off; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backup.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | remote_user: pi 3 | become_method: sudo 4 | name: "Backup Files" 5 | tasks: 6 | - name: Backup files 7 | command: tar cvf backup-files.tar files.adrianistan.eu/data 8 | args: 9 | chdir: /home/pi 10 | 11 | - name: Download files backup 12 | fetch: 13 | src: /home/pi/backup-files.tar 14 | dest: backups/files.tar 15 | flat: yes 16 | 17 | - name: Compress files Backup 18 | local_action: archive 19 | args: 20 | path: 21 | - backups/files.tar 22 | dest: backups/files-{{ ansible_date_time.date }}.tar.xz 23 | format: xz 24 | -------------------------------------------------------------------------------- /app.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(http/thread_httpd)). 2 | :- use_module(library(http/http_dispatch)). 3 | :- use_module(library(http/html_write)). 4 | :- use_module(library(http/http_header)). 5 | :- use_module(library(http/http_client)). 6 | :- use_module(library(http/http_multipart_plugin)). 7 | :- use_module(library(http/http_authenticate)). 8 | :- use_module(library(http/http_unix_daemon)). 9 | :- use_module(library(http/http_files)). 10 | :- use_module('config.pl'). 11 | 12 | %server(Port) :- 13 | % http_server(http_dispatch, [port(Port),workers(1)]). 14 | 15 | :- http_handler(/,index,[method(get)]). 16 | :- http_handler(root(upload),upload,[method(post)]). 17 | :- http_handler(root(Path),static(Path),[method(get)]). 18 | 19 | %:- http_handler(root(.), http_reply_from_files('.', []), [prefix]). 20 | 21 | auth(Request) :- 22 | Realm = 'Files Adrianistan', 23 | ( 24 | config(Username,StrPassword), 25 | string_codes(StrPassword,Password), 26 | member(authorization(Header),Request),http_authorization_data(Header,basic(Username,Password)) -> true 27 | ; 28 | throw(http_reply(authorise(basic, Realm))) 29 | ). 30 | 31 | static(Path,Request) :- 32 | string_concat('data/',Path,RealPath), 33 | atom_string(AtomPath,RealPath), 34 | http_reply_file(AtomPath,[],Request). 35 | 36 | 37 | index(Request) :- 38 | auth(Request), 39 | phrase( 40 | index_html, 41 | TokenHTML, 42 | [] 43 | ), 44 | format('Content-Type: text/html~n~n'), 45 | print_html(TokenHTML). 46 | 47 | index_html --> 48 | html([ 49 | head([ 50 | title('Files Adrianistán'), 51 | meta(charset=utf8) 52 | ]), 53 | body([ 54 | h1('Files Adrianistan'), 55 | p('Usa el formulario para subir un archivo, si se ha subido correctamente te redirigirá a la URL que puedes usar para compartir'), 56 | form([action='/upload',method=post,enctype='multipart/form-data'],[ 57 | input([type=file,name=file]), 58 | input([type=submit,value='Subir fichero']) 59 | ]) 60 | ]) 61 | ]). 62 | 63 | upload(Request) :- 64 | multipart_post_request(Request), !, 65 | http_read_data(Request, Parts, 66 | [ on_filename(save_file) 67 | ]), 68 | memberchk(file=file(FileName, _Saved), Parts), 69 | http_redirect(moved,root(FileName),Request). 70 | 71 | upload(_Request) :- 72 | throw(http_reply(bad_request(bad_file_upload))). 73 | 74 | multipart_post_request(Request) :- 75 | memberchk(method(post), Request), 76 | memberchk(content_type(ContentType), Request), 77 | http_parse_header_value( 78 | content_type, ContentType, 79 | media(multipart/'form-data', _)). 80 | 81 | :- public save_file/3. 82 | 83 | save_file(In, file(FileName, FileOut), Options) :- 84 | option(filename(FileName), Options), 85 | string_concat('data/',FileName,FileOut), 86 | setup_call_cleanup( 87 | open(FileOut,write,Stream,[encoding(octet)]), 88 | copy_stream_data(In, Stream), 89 | close(Stream)). 90 | 91 | run :- 92 | %server(2345), 93 | http_daemon([port(2345),fork(false)]). 94 | 95 | :- run. 96 | --------------------------------------------------------------------------------