To return space to the OS, use
VACUUM FULL. While being at it, I suppose you run
VACUUM FULL ANALYZE. I quote the manual:
Selects "full" vacuum, which can reclaim more space, but takes much
longer and exclusively locks the table. This method also requires
extra disk space, since it writes a new copy of the table and doesn't
release the old copy until the operation is complete. Usually this
should only be used when a significant amount of space needs to be
reclaimed from within the table.
Bold emphasis mine.
CLUSTER achieves that, too, as a collateral effect.
VACUUM, you achieve "one or more pages at the end of a table entirely free" only by chance - the tuples stored last physically get deleted.
This happens, for instance, when you
INSERT a batch of rows and
DELETE them before other tuples get appended by
INSERT. or it can happen by chance, if you delete a lot of rows (including those appended last).
You need wiggle room on your disk for any of these operations. There is also the community tool
pg_repack as replacement for
VACUUM FULL /
CLUSTER. It avoids exclusive locks, but that, too, needs free space on disk. Quoting the manual
Requires free disk space twice as large as the target table(s) and indexes.
As a last resort, you can run a dump/restore cycle. That removes all bloat from tables and indexes, too. There is a closely related question here on dba.SE:
I need to run VACUUM FULL with no available disk space
The answer over there is pretty radical. If your situation allows for it (no foreign keys or other references preventing that you delete rows), you can just:
Dump the table to disk connecting from a remote computer with plenty of disk space (
pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql
TRUNCATE the table in the DB:
INSERT original rows to same table from the remote connection.
psql -h <host_name> -p <port> mydb -f db_mytbl.sql
It is now free of any dead rows or bloat.
But maybe you can have that simpler?
Can you make enough space on disk by deleting (moving) unrelated files?
VACUUM FULL smaller tables first, one by one, thereby freeing up enough disk space?
Can you run
REINDEX TABLE or
REINDEX INDEX to free disk space from bloated indexes?
Whatever you do, don't be rash. If in doubt, backup everything to a remote location first.