Your web space

Every account has web space. There is nothing to enable — the directory already exists.

Where it is

On the box
~/public_html
On the web
https://shell.shadowsquad.org/home/~yourname

The ~name URL is the old Unix convention, and it is deliberate: this is a shell account with a web space attached, not a hosting product with a shell attached.

Your first page

mkdir -p ~/public_html
cat > ~/public_html/index.html <<'EOF'
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>yourname</title></head>
<body>
<h1>yourname</h1>
<p>Hello from a shell account.</p>
</body>
</html>
EOF
chmod 755 ~/public_html
chmod 644 ~/public_html/index.html

Load the URL. That is the whole process.

Permissions

Your home directory stays private — mode 0750, no other account can even list it. The web server is granted permission to walk through it to public_html, and nothing more, by a file ACL set when your account is created. You do not have to loosen anything to make your site work.

Files need to be readable to be served:

chmod 755 ~/public_html
find ~/public_html -type f -exec chmod 644 {} +
find ~/public_html -type d -exec chmod 755 {} +

A 403 on a directory usually means it has no index.html — directory listings are off. A 403 on a file usually means it is mode 600.

Anything in public_html is public. Dotfiles are refused by the server, but do not treat that as a security feature: keep secrets out of the directory entirely.

PHP

PHP works. Name the file .php and it runs — including as the index of a directory, so index.php is served for /home/~you/ just as index.html is. If a directory has both, the HTML one wins.

Name the file .php and it runs:

cat > ~/public_html/time.php <<'EOF'
<?php
header('Content-Type: text/plain');
echo "Server time: ", date('Y-m-d H:i:s'), " UTC\\
";
EOF

Two things about how PHP runs here, both worth knowing before you build something that depends on the opposite:

  • It runs as the web server, not as you. So a script can read what is world-readable, and it cannot write into your home directory — that is why an upload form or a file-based counter will fail. Making your files writable by everyone would fix it and is not something to do on a shared machine; ask staff if you need writable storage.
  • Shell execution is disabled. exec, shell_exec, system, proc_open, popen and curl_exec are all off, and PHP is confined to /home. Normal for shared hosting, and it means a page cannot start a bot for you.

A page something else writes

The section above is a list of things PHP cannot do here: it runs as the web server, it cannot write into your home directory, and it cannot start a bot for you. That sounds like a limitation until you turn it round. Anything you run as yourself can write into public_html, and the web server will happily serve it. No PHP, no database, no framework — just a file that appears.

A live example on this box: the ShadowSquad channel stats page. An eggdrop sitting in #shadowsquad writes a plain HTML file into its web space once a minute — who is in the channel, how many messages it has seen, which commands people used, who talks most. The page carries a <meta http-equiv="refresh" content="60"> so a browser left open keeps up with it.

The pattern is worth copying for anything with numbers in it — a bot, a build, a backup job, a script that watches something:

#!/bin/sh
# Write to a temporary file, then move it into place. A move within the same
# filesystem is atomic, so nobody ever loads the page halfway through being
# written.
out=~/public_html/index.html
tmp=$(mktemp ~/public_html/.stats-XXXXXX)

{
  echo '<!doctype html><meta charset="utf-8">'
  echo "<title>my bot</title>"
  echo "<p>Updated $(date -u '+%Y-%m-%d %H:%M UTC')</p>"
  # ... whatever you actually want to say
} > "$tmp"

chmod 644 "$tmp"
mv "$tmp" "$out"

Run it from your crontab (crontab -e) as often as makes sense. Once a minute is plenty for most things and costs nothing; every second is a good way to be asked to stop.

Two details in that script are the whole trick. Writing to a temporary file and moving it into place means a reader never sees half a page. And the temporary file starts with a dot, so even in the moment it exists the web server refuses to serve it.

Databases

Plans from Standard upwards include MySQL databases, and they are created from the control panel — see the database guide. Your PHP pages connect to them on localhost with the credentials shown when you create one.

Keeping it updated

From your own machine:

rsync -avz --delete site/ yourname@shell.shadowsquad.org:~/public_html/

Or keep the site in git and pull on the box:

cd ~/public_html
git init
git remote add origin https://github.com/you/yoursite.git
git pull origin main

If you do that, remember ~/public_html/.git would be readable — the server refuses dotfiles, but the tidier arrangement is to clone elsewhere and copy the built output in.

What this space is for

A homepage, project pages, documentation for your bot, a place to park a file so you can link someone to it. It is not a CDN, a file-sharing service, or somewhere to host a download mirror; the acceptable use policy is the long version of that sentence.

« All guides