Skip to content

Commit

Permalink
Added file-manager
Browse files Browse the repository at this point in the history
  • Loading branch information
rgaudin committed Jan 8, 2024
1 parent 4ba1ddc commit 14dab25
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/docker_file-manager.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Publish file-manager Image

on:
push:
branches:
- 'main'
paths:
- 'file-manager/*'
tags:
- 'file-manager-*'

jobs:
file-manager:
name: Publish file-manager Image
runs-on: ubuntu-22.04
steps:
- uses: actions/[email protected]
- name: Publish file-manager Image
uses: openzim/docker-publish-action@v10
with:
image-name: offspot/file-manager
on-master: dev
build-args:
VERSION={tag}
tag-pattern: /^file-manager-([0-9.]+)$/
restrict-to: offspot/container-images
platforms: |
linux/amd64
linux/arm64
context: file-manager
registries: ghcr.io
credentials:
GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }}
GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }}
1 change: 1 addition & 0 deletions file-manager/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tinyfilemanager.php
87 changes: 87 additions & 0 deletions file-manager/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
FROM alpine:3.19
LABEL org.opencontainers.image.source https://github.com/offspot/container-images

ENV WEBDIR "/var/www/html"

RUN apk add --no-cache \
dumb-init \
lighttpd \
curl \
php83-fpm php83-fileinfo php83-iconv php83-zip php83-mbstring php83-session php83-phar php83-ctype php83-posix

WORKDIR /var/www/html

RUN set -e \
&& TFMREF="8e87afae5b744c3e23490000bf0d398d6d4a749c" \
&& TFMPREFIX="https://raw.githubusercontent.com/prasathmani/tinyfilemanager/$TFMREF/" \
&& mkdir -p $WEBDIR/assets/css $WEBDIR/assets/js $WEBDIR/assets/fonts \
&& cd $WEBDIR/assets/css \
&& curl -L -O https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css \
&& curl -L -O https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.css.map \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.css \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/vs.min.css \
&& echo "CSS OK" \
&& cd $WEBDIR/assets/fonts \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/FontAwesome.otf \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.eot \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.svg \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.ttf \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.woff \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2 \
&& echo "FONTS OK" \
&& cd $WEBDIR/assets/js \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js \
&& curl -L -O https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js \
&& curl -L -O https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.js.map \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js \
&& curl -L -O https://code.jquery.com/jquery-3.6.1.min.js \
&& curl -L -O https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js \
&& curl -L -O https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js \
&& echo "JS OK" \
&& cd $WEBDIR \
&& curl -L -O "$TFMPREFIX/translation.json" \
&& curl -L -O "$TFMPREFIX/tinyfilemanager.php" \
&& mkdir -p /data

RUN apk del curl

# patch TFM to disable in-php downloader

# replace head of file to change the external assets
RUN lnum=$(grep -n -F "EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL" tinyfilemanager.php | cut -d ':' -f 1) \
&& printf "<?php\n\
\$config_file = __DIR__.'/config.php';\n\
if (is_readable(\$config_file)) {\n\
@include(\$config_file);\n\
}\n" > index.php \
&& tail -n +$lnum tinyfilemanager.php >> index.php \
&& cat index.php

COPY lighttpd.conf /etc/lighttpd/lighttpd.conf
COPY config.php /var/www/html
COPY listing_auth.php /var/www/html
COPY manager_auth.php /var/www/html
COPY entrypoint /usr/local/bin/

# there are three modes:
# - listing: lists the content of /data read-only
# - manager: auth-required, /data is in read-write
# - mixed: listing mode on / endpoint but manager on /admin/ endpoint
ENV ACCESS_MODE "listing"

# authentication for manager and mixed modes (plaintext)
ENV ADMIN_USERNAME "admin"
ENV ADMIN_PASSWORD "admin@123"

# timezone to use for date/time (assuming host has date)
# /!\ must be escaped! (slash)
ENV UI_TIMEZONE "Etc\/UTC"

ENV UI_LANG "en"

ENV APP_URL ""

EXPOSE 80
ENTRYPOINT ["/usr/bin/dumb-init", "--", "entrypoint"]
CMD ["lighttpd", "-D", "-f", "/etc/lighttpd/lighttpd.conf"]
25 changes: 25 additions & 0 deletions file-manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# file-browser

A [tinyfilemanager](https://github.com/prasathmani/tinyfilemanager)-based image for managing on-device files

## Usage

```sh
docker run -p 80:80 -v /some/folder:/data:ro ghcr.io/offspot/file-manager
```

## Configuration

Just mount your files tree to `/data`. If you don't plan on editing them, mount it read-only.

Configuration is done most via environment variables

| Variable | Default | Usage |
| ------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `ACCESS_MODE` | `listing` | One of `listing` (no auth, read-only), `manager` (auth-required, editable) and `mixed` (`listing` on `/` and `manager` on `/admin/`) |
| `APP_URL` | | URL to the app. Not used in `mixed` mode. Allows better-looking URLs (`index.php` not visible) |
| `UI_LANG` | `en` | UI Language (ISO-636-1), must be a supported one |
| `UI_TIMEZONE` | `Etc/UTC` | Timezone to use to display file details. ⚠️ `/` must be escaped |
| `ADMIN_USERNAME` | `admin` | Username for authentication (for `manager` and `mixed`) modes |
| `ADMIN_PASSWORD` | `admin@123` | Password for authentication (for `manager` and `mixed`) modes |

143 changes: 143 additions & 0 deletions file-manager/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
error_reporting(E_ERROR | E_PARSE);
//Default Configuration
$CONFIG = '{"lang":"UI_LANG","error_reporting":false,"show_hidden":false,"hide_Cols":true,"theme":"light"}';

define('VERSION', '2.5.3-offspot');
define('APP_TITLE', 'File Manager');
$app_url = 'APP_URL';
if ($app_url) {
define('FM_SELF_URL', $app_url);
}

// include auth file to switch modes
$auth_file = __DIR__.'/auth.php';
// echo $auth_file;
if (is_readable($auth_file)) {
@include($auth_file);
}

// Readonly users
// e.g. array('users', 'guest', ...)
$readonly_users = array(
);

// user specific directories
// array('Username' => 'Directory path', 'Username2' => 'Directory path', ...)
$directories_users = array();

// Enable highlight.js (https://highlightjs.org/) on view's page
$use_highlightjs = true;

// highlight.js style
// for dark theme use 'ir-black'
$highlightjs_style = 'vs';

// Enable ace.js (https://ace.c9.io/) on view's page
$edit_files = true;

// Default timezone for date() and time()
// Doc - http://php.net/manual/en/timezones.php
$default_timezone = 'UI_TIMEZONE';

// Root path for file manager
// use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder'
$root_path = '/data';

// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
// Will not working if $root_path will be outside of server document root
$root_url = '/_download';

// Server hostname. Can set manually if wrong
// $_SERVER['HTTP_HOST'].'/folder'
$http_host = $_SERVER['HTTP_HOST'];

// input encoding for iconv
$iconv_input_encoding = 'UTF-8';

// date() format for file modification date
// Doc - https://www.php.net/manual/en/function.date.php
$datetime_format = 'd/m/Y g:i A';

// Path display mode when viewing file information
// 'full' => show full path
// 'relative' => show path relative to root_path
// 'host' => show path on the host
$path_display_mode = 'relative';

// Allowed file extensions for create and rename files
// e.g. 'txt,html,css,js'
$allowed_file_extensions = '';

// Allowed file extensions for upload files
// e.g. 'gif,png,jpg,html,txt'
$allowed_upload_extensions = '';

// Favicon path. This can be either a full url to an .PNG image, or a path based on the document root.
// full path, e.g http://example.com/favicon.png
// local path, e.g images/icons/favicon.png
$favicon_path = '';

// Files and folders to excluded from listing
// e.g. array('myfile.html', 'personal-folder', '*.php', ...)
$exclude_items = array();

// Online office Docs Viewer
// Availabe rules are 'google', 'microsoft' or false
// Google => View documents using Google Docs Viewer
// Microsoft => View documents using Microsoft Web Apps Viewer
// false => disable online doc viewer
$online_viewer = 'false';

// Sticky Nav bar
// true => enable sticky header
// false => disable sticky header
$sticky_navbar = false;

// Maximum file upload size
// Increase the following values in php.ini to work properly
// memory_limit, upload_max_filesize, post_max_size
$max_upload_size_bytes = 20000000000; // size 5,000,000,000 bytes (~5GB)

// chunk size used for upload
// eg. decrease to 1MB if nginx reports problem 413 entity too large
$upload_chunk_size_bytes = 2000000; // chunk size 2,000,000 bytes (~2MB)

// Possible rules are 'OFF', 'AND' or 'OR'
// OFF => Don't check connection IP, defaults to OFF
// AND => Connection must be on the whitelist, and not on the blacklist
// OR => Connection must be on the whitelist, or not on the blacklist
$ip_ruleset = 'OFF';

// Should users be notified of their block?
$ip_silent = true;

// IP-addresses, both ipv4 and ipv6
$ip_whitelist = array(
'127.0.0.1', // local ipv4
'::1' // local ipv6
);

// IP-addresses, both ipv4 and ipv6
$ip_blacklist = array(
'0.0.0.0', // non-routable meta ipv4
'::' // non-routable meta ipv6
);

// External CDN resources that can be used in the HTML (replace for GDPR compliance)
$external = array(
'css-bootstrap' => '<link href="/assets/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">',
'css-dropzone' => '<link href="/assets/css/dropzone.min.css" rel="stylesheet">',
'css-font-awesome' => '<link rel="stylesheet" href="/assets/css/font-awesome.min.css" crossorigin="anonymous">',
'css-highlightjs' => '<link rel="stylesheet" href="/assets/css/' . $highlightjs_style . '.min.css">',
'js-ace' => '<script src="/assets/js/ace.js"></script>',
'js-bootstrap' => '<script src="/assets/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>',
'js-dropzone' => '<script src="/assets/js/dropzone.min.js"></script>',
'js-jquery' => '<script src="/assets/js/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>',
'js-jquery-datatables' => '<script src="/assets/js/jquery.dataTables.min.js" crossorigin="anonymous" defer></script>',
'js-highlightjs' => '<script src="/assets/js/highlight.min.js"></script>',
'pre-jsdelivr' => '<style type="text/css">form[action*="dl="], a[href*="&dl="] { background-color: red; display:none !important; }\na[href*="/_download/"] { } i.fa.fa-link::before { content: "\f019" !important; }</style>',
'pre-cloudflare' => ''
);

?>
51 changes: 51 additions & 0 deletions file-manager/entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/sh
set -e

echo "set credentials"
sed -i "s/ADMIN_USERNAME/${ADMIN_USERNAME}/g" manager_auth.php
sed -i "s/ADMIN_PASSWORD/${ADMIN_PASSWORD}/g" manager_auth.php

# mixed mode cannot set APP_URL as there are two apps
if [[ "$ACCESS_MODE" = "mixed" ]]
then
unset APP_URL
fi

# static replacement for envs (so we can keep clear_env=yes)
echo "set statics"
sed -i "s/UI_TIMEZONE/${UI_TIMEZONE}/g" config.php
sed -i "s/UI_LANG/${UI_LANG}/g" config.php
sed -i "s/APP_URL/${APP_URL}/g" config.php

echo "configuring for ${ACCESS_MODE}"
if [[ "$ACCESS_MODE" = "listing" ]]
then
ln -s listing_auth.php auth.php

elif [[ "$ACCESS_MODE" = "manager" ]]
then

ln -s manager_auth.php auth.php

elif [[ "$ACCESS_MODE" = "mixed" ]]
then
mkdir -p admin
cd admin
cp ../index.php index.php
cp ../config.php config.php
cp ../manager_auth.php auth.php
cd ..
ln -s listing_auth.php auth.php
else
echo "Unsupported mode: ${ACCESS_MODE}"
exit 1
fi

ls -l
cat config.php
cat auth.php
cat manager_auth.php

php-fpm83 -D

exec "$@"
17 changes: 17 additions & 0 deletions file-manager/lighttpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
server.document-root = "/var/www/html"

server.modules += ("mod_accesslog")
server.modules += ("mod_deflate")
server.errorlog = "/dev/fd/2"
accesslog.filename = "/dev/fd/2"

server.modules += ( "mod_fastcgi" )
fastcgi.server = ( ".php" => ((
"host" => "127.0.0.1",
"port" => "9000"
)))

index-file.names = ( "index.html", "index.php" )

server.modules += ("mod_alias")
alias.url = ( "/_download/" => "/data/" )
12 changes: 12 additions & 0 deletions file-manager/listing_auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

// Auth with login/password
// set true/false to enable/disable it
// Is independent from IP white- and blacklisting
$use_auth = false;

// Global readonly, including when auth is not being used
$global_readonly = true;


?>
18 changes: 18 additions & 0 deletions file-manager/manager_auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

// Auth with login/password
// set true/false to enable/disable it
// Is independent from IP white- and blacklisting
$use_auth = true;

// Global readonly, including when auth is not being used
$global_readonly = false;

// Login user name and password
// Users: array('Username' => 'Password', 'Username2' => 'Password2', ...)
// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
$auth_users = array(
'ADMIN_USERNAME' => password_hash('ADMIN_PASSWORD', PASSWORD_DEFAULT),
);

?>

0 comments on commit 14dab25

Please sign in to comment.