Panblog
This Node.JS application serves as a system to store and manage blog posts. Powered by the pandoc application, it will accept and store files in a variety of formats, and then return HTML versions upon request.
Post files of a variety of formats (markdown, org files, Microsoft Word files, etc.) can be stored in the upload folder (defaults to /var/lib/panblog/uploads). Then, the application will automatically convert them to HTML (storing the output in various subfolders of /var/cache/panblog) and then return them when HTTP requests to http://localhost/post are made. Posts can also be uploaded by submitting the files to http://localhost/upload.
Notes on Security
This application has little support for security built in. By default, it will accept any and all requests without further validation, and only supports basic header authorization. It also has no support for SSL. It is not designed to be directly exposed to the wider internet. Instead, it should be put behind a more feature-filled server application (i.e. a PHP web server) that will work as a middle-man.
Requirements
This application requires that pandoc is installed on the machine. If you utilize the docker image, Pandoc will be included in the image.
Filesystem
The application expects full usage of two directories and read-access to one file. The exact paths can be configured (see below), but the paths and permissions should be prepared before launching.
/var/lib/panblog- Where uploads will be read from and metadata will be stored./var/cache/panblog- Where HTML output is written to./etc/panblog/config- A configuration file. May be read-only.
Paths
The application provides the following paths:
/ping
A GET path to test the application. Returns the string "pong."
/error
A GET path to test the application's error handling.
/refresh
A POST path to re-read the raw posts and recalculate the index.
/verify
A POST path to get metadata of a post file, returning a JSON string.
If a GET request is sent to the path, a basic HTML form will be returned that will allow for uploading a file to this path. This is only meant for testing purposes.
/upload
A POST path to submit a new blog post to the application. Upon success, a basic web page will be returned.
If a GET request is sent to the path, a basic HTML form will be returned that will allow for uploading a file to this path. This is only meant for testing purposes.
/feed
Returns the RSS feed for the blog, calculating it as needed.
/feed.xml
An alias for /feed.xml
/feed.atom
An alias for /feed.xml
/feed.rss
An alias for /feed.xml
/atom
An alias for /feed.xml
/atom.xml
An alias for /feed.xml
/rss
An alias for /feed.xml
/rss.atom
An alias for /feed.xml
/rss.xml
An alias for /feed.xml
/post
One of the more complex paths, GET requests here allow for viewing of a post. If a request is send to just /post, then a JSON list of uploaded posts is returned. However, by specifying further subpath elements, a specific post can be searched for and returned.
Here are parameters you can add:
author
The slug (lower-case, all non-alphanumeric characters replaced by a dash) of the author that uploaded the post.
date
The date the post was drafted, either in the format of "yyyy-mm-dd" or as a series of subpaths like "/yyyy/mm/dd." Alternate orderings are acceptable.
keyword
A keyword that applies to the post.
title
The slug of the post title.
If the search only results in a single post, the HTML page of that post is returned. Otherwise, a JSON list of different posts is returned. To obtain a specific post, an index number can be appended.
By default, if a single post is found, an example HTML page is returned. However, by specifying a file name as the final element of the path, other files can be returned. This will usually be image files or other assets uploaded alongside the blog post. However, a few file paths return special output:
metadata.json
Returns the JSON of the post metadata.
fragment.html
The HTML version of the post without surrounding tags. Useful to be called by the frontend for embedding into a template.
index.html
The HTML version of the post using a default template.
Configuration
The application pulls configuration details from two sources. The first one is from the configuration file. It will read each line, expecting the format of "key = value" and use the equal sign (with optional whitespace included) as the delimiter. The configuration file is by default expected at /etc/panblog/config, but this can be configured by setting the environment variable PANBLOG_CONFIG_PATH.
The second source is from environment variables. Any variable name with the PANBLOG_ prefix will be read into the configuration. In the event that a configuration key is specified in both the configuration file and an environmental variable, the value stored in the environmental variable takes precedence.
Note that as well as raw values, configuration values can store a reference to a seperate location where the resolved value is stored. If a configuration value begins with a file: prefix, the resolved value will be read from the local file system. Likewise, if a configuration value begins with a url: prefix, the configuration value will be read from the results of a GET query to that value. For example, if "auth_key" is set to "file:/run/secrets/blog-secret," then the application will pull the "auth_key" value from the file "/run/secrets/blog-secret."
These are the following configuration values:
blog_frontend
This is the URL that will lead the user to the website that has the blog. This is used when generating the Atom feed, so be sure to include any subpaths leading up to the blog. It should not end in a forward slash. Defaults to the operating system host name.
blog_id
The URI identifier of the blog. This can usually just be the URL of the website. Defaults to a random UUID formatted as "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx."
blog_title
The human-readable title of the website. Defaults to "New Blog."
blog_author
The name of the primary author of the blog. Multiple authors can be specified by separating each one with a comma.
blog_link
The URL to the blog. Will usually be the same as BLOG_FRONTEND. It should not end in a forward slash. Optional.
blog_categories
A comma-separated list of keywords that apply to the blog as a whole. Optional.
blog_contributor
A comma-separated list of names of people who contributed to the blog. Optional.
blog_icon
The URL to the blog favicon. Optional.
blog_logo
The URL to the blog logo image. Optional.
blog_rights
A copyright string for the blog. Optional.
blog_subtitle
A subtitle for the blog. Optional.
base_url
By default, all paths for this application are accessible from directly under the top-level domain this is hosted on. Specifying this variable will set the application to listen for these paths as a subpath of what is specified here. For example, if base_url is set to "/blog," then posts must be accessed by querying "http://localhost/blog/post", as opposed to just "http://localhost/post."
upload_path
The path to the directory that all post uploads are stored. It should not end in a forward slash. Defaults to "/var/lib/panblog/uploads."
cache_path
The path to the directory that all processed post uploads will be sent to. It should not end in a forward slash. Defaults to "/var/cache/panblog/output."
index_path
The path to the file that the blog post index should be written to. Defaults to "/var/cache/panblog/index.json."
tmp_path
The path to the directory that temporary files will be written to. It should not end in a forward slash. Defaults to "/var/cache/panblog/tmp."
tmp_upload_path
This variable controls where the files uploaded through the /upload path are sent for processing. It should not end in a forward slash. Defaults to "/var/cache/panblog/upload" (note the lack of the plural).
max_upload_size
This variables controls the maximum payload size of anything sent through the /upload and /verify paths, in bytes. Defaults to 10 MiB.
auth_key
By default, all valid requests are accepted by the application. If an auth key is specified, Any requests that do not have this header present as a "Authentication: Basic " http header will be rejected with a 401 error.
auth_key_hash
Identical to auth_key, but instead stores the bcrypt hash of the authentication key you want to use.