Skip to content

Latest commit

Β 

History

3,082 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

geesome

File Storage and Social Media Node

Current state: 0.4.1 - Beta

opened issues closed issues closed PR opened PR


Contributions Welcome Join Us On Telegram

GeeSome Node

GeeSome Node allows you to run your own file storage with social media functional: make you own public or private group with posts and content. It's a Node on top of IPFS for define and manage data structure of files, users and groups. Node provides an UI and API for storing and accessing your saved data or remote data of other nodes: files, posts, groups.

GeeSome Main Page

Documentation

A running node also exposes docs discovery for tools and agents: GET /v1, GET /v1/openapi.json, GET /v1/apidoc.json, and conventional OpenAPI paths such as /.well-known/openapi.json.

About GeeSome Project

GeeSome protocol created to provide communication tool between communities of property owners in Galt Project.

Galt Project team is aware of many cases of censorship and blocking in different social networks. These cases forced us to develop a new decentralized protocol and node application that would allow anyone to upload any content to his personal node and to share this content with the whole world without the risk of being blocked.

Using the GeeSome protocol, communities in the Galt Project should eventually be able to communicate in end-to-end encrypted chat groups, share images, video, text or any data. Browser-encrypted direct messages and attachments now keep device private keys, plaintext, and attachment keys outside GeeSome nodes, which store and route opaque ciphertext. Production-ready group chat still requires a maintained MLS implementation, membership/key-rotation flows, and real multi-node browser verification.

We are sure that this tool should be used not only by the project's communities, but also by anyone who is concerned about the safety of their data, censorship and blocking in web.

GeeSome Protocol

A new open protocol for unstopable social networking and communication on IPFS. It defines the structure of social network data to describe familiar to the modern user entities: content, posts, tags, groups.

GeeSome UI

GeeSome UI - it's Vue application, that using GeeSome node API for saving content and IPFS in-browser node for getting content. It's completly separated client from node and can be connected to any other GeeSome node. There are also many cases when it’s not necessary to use GeeSome UI. You can use GeeSome node API and GeesomeClient library in your project to build you own UI with some important features special for you.

Summary

With the help of GeeSome Node, anyone can create an instance of a decentralized social network, with groups like in YouTube, Instagram or Telegram but with content preservation and no locks or censorship thanks to the concept of personal GeeSome Node using IPFS Node to store content, access data and receive updates by libp2p.

GeeSome Node can be used:

  • to create and maintain your blog and generate static site for blog
  • to save important content like Saved messages in telegrams and / or in the form of a file structure as in Google Drive
  • as a media platform for adding and viewing / listening to audio and video content, creating playlists
  • to share the uploaded content in any form (blog, playlist, file, folder)
  • to create groups and, after frontend E2EE work is complete, communicate with your friends in secure chats

GeeSome Scheme

GeeSome-Scheme

You can run personal or public GeeSome node. It used for storing files, manage entities and prepare content for publishing. Also because of IPNS updates issues - GeeSome node have IPNS caching based on signed PubSub events. Also there is an issue about IPNS keys of user. Currently its storing in GeeSome node, but need to improve it.

UI Screenshots

File explorer

GeeSome File explorer

Test group

GeeSome Test Group

Personal chat proof of concept

GeeSome Personal Chat

Mobile version

Main page Menu Groups list Group page
GeeSome Mobile UI GeeSome Mobile UI GeeSome Mobile UI GeeSome Mobile UI

Install with domain to your server

  1. Set A DNS record for your geesome.your-site.com domain with ip address of server
  2. [Recommended] If you want to use gateway - set A DNS record for your gateway.geesome.your-site.com domain with ip address of server
  3. Clone repo to server that bound to domain
git clone https://github.com/galtproject/geesome-node.git && cd geesome-node
  1. [Recommended] actions before install:
sudo SIZE=8G bash/ubuntu-init-swapfile.sh # Init 8GB Swapfile
sudo PORT=4242 bash/ubuntu-set-ssh-port.sh # Change SSH port to custom
  1. Run bash script with parameters: domain and email for letsencrypt
sudo chmod +x bash/*.sh && sudo bash/ubuntu-install-docker.sh
sudo DOMAIN=geesome.your-site.com EMAIL=your@email.com GATEWAY=1 bash/ubuntu-install-nginx.sh # add CF=1 before script to install for cloudflare

The Docker service runs bash/ipfs-ownership-preflight.sh before startup. It creates the mounted IPFS data directories for Kubo's ipfs user (1000:100) and conditionally repairs restored or upgraded repos whose config, repo.lock, datastore, or blocks ownership would otherwise crash-loop the IPFS container.

  1. Open geesome.your-site.com/#/setup to create first admin user

Moving Docker storage to a mounted disk

If the server runs out of root disk space, mount a larger disk first, then move the heavy Docker storage with one command from the repo directory:

sudo bash/move-docker-storage.sh ipfs /mnt/geesome --yes      # creates /mnt/geesome/ipfs and /mnt/geesome/ipfs-staging
sudo bash/move-docker-storage.sh database /mnt/geesome --yes  # creates /mnt/geesome/postgres-data
sudo bash/move-docker-storage.sh all /mnt/geesome --yes       # creates all of the above

The /mnt/geesome argument is the parent directory, not the final data directory. The ipfs target moves STORAGE_DATA to /mnt/geesome/ipfs and STORAGE_STAGING to /mnt/geesome/ipfs-staging. The database target moves Postgres data to /mnt/geesome/postgres-data. The script stops the Docker stack before copying, copies and verifies the data, updates Docker Compose .env automatically, writes a geesome-docker systemd storage override when that service is installed, relinks the old paths, runs the IPFS ownership preflight when needed, and starts the stack again. Add --no-restart only if you want to leave the stack stopped after the move.

By default the old source directories are deleted after the stack starts successfully, freeing space on the original disk. Add --keep-source if you want rollback directories left as *.moved-<timestamp> backups instead.

Install without domain (IP only)

Use this if your server has no domain and you want to reach the node by its IP address.

  1. Clone repo to server
git clone https://github.com/galtproject/geesome-node.git && cd geesome-node
  1. [Recommended] actions before install:
sudo SIZE=8G bash/ubuntu-init-swapfile.sh # Init 8GB Swapfile
sudo PORT=4242 bash/ubuntu-set-ssh-port.sh # Change SSH port to custom
  1. Install Docker and build/start the node:
sudo chmod +x bash/*.sh && sudo bash/ubuntu-install-docker.sh
  1. Configure nginx for IP access and create the first admin user:
bash/ubuntu-install-nginx-nodomain.sh

The script serves the node on http://<server-ip>/ (API proxied at http://<server-ip>/api/), waits for the node, prompts for the admin username, email and password, creates the first admin user, and prints the API auth token. Copy the token from the output β€” you can use it for API requests.

Note: the browser UI will not work over plain http://<server-ip>. Chrome and other modern browsers restrict secure-context-only APIs (Web Crypto, service workers, etc.) that the GeeSome UI relies on to HTTPS origins (or localhost). The node and its HTTP API work fine over IP β€” this setup is intended for API/headless use or local access. To use the browser UI, install with a domain and TLS (see Install with domain) or tunnel the node to localhost on your own machine.

How to use gateway

  1. Set A DNS record for your gateway.geesome.your-site.com domain with ip address of server
  2. Set CNAME DNS record for your your-site.com or blog.your-site.com(for example) with gateway domain: gateway.geesome.your-site.com
  3. Set TXT DNS record for your your-site.com or blog.your-site.com(for example) with IPFS or IPNS content: dnslink=/ipns/bafzbeidjvkkvlsfeko4s43lhvi3zd4phlkfoudhf6ygqatl4rrveigmdi4
  4. Run bash script with parameters: domain and email for letsencrypt
sudo DOMAIN=your-site.com EMAIL=your@email.com bash/ubuntu-cert-domain.sh

Note: You can generate a static site from Geesome groups by UI and get IPNS or IPFS of static sites for the gateway using.

Getting updates

npm run docker-upgrade

You can also invoke bash bash/docker-upgrade directly. The old bash/docker-rebuild-and-upgrade.sh remains a compatibility wrapper.

This runs bash/docker-upgrade: it pulls the latest source, selects a verified published image for that Git commit (or builds locally when unavailable), and restarts the geesome-docker systemd service.

The Docker rebuild keeps dependency and BuildKit caches warm, so source-only updates should not redownload packages. When the Docker builder supports external cache exports, the build also imports/exports .docker-build-cache; otherwise it falls back to normal Docker layer caching. A failed image preparation stops the upgrade before service restart; caches are not automatically pruned.

Warning: the upgrade script refuses to run with uncommitted local git changes. Commit or stash server-side edits before running it.

GeeSome handles SIGTERM and SIGINT by closing public HTTP ingress, draining module workers, and closing the database last. The default application shutdown deadline is 30 seconds. Set GEESOME_SHUTDOWN_TIMEOUT_MS to change it, and keep GEESOME_DOCKER_STOP_GRACE_PERIOD longer than that deadline when running through Docker Compose; the included Compose defaults are 30000 milliseconds and 35s respectively.

Optional media tools

YouTube thumbnail and video import drivers use the local yt-dlp binary. Install yt-dlp on hosts that need YouTube imports, or set YT_DLP_BINARY=/path/to/yt-dlp before starting GeeSome Node.

Invite code security

Invite codes are generated as crypto-random base62 strings. The default length is 16 characters; set GEESOME_INVITE_CODE_LENGTH before startup to use a longer code. Values below 16 are ignored.

Debugging and logs

Logs are quiet by default. See DEBUG.md for debug namespaces, log flags, and memory profiling (including how to dump per-process memory to a file for sizing hardware requirements).

Getting started with GeeSome Node API

  1. Install GeeSome libs by npm:
npm i --save git://github.com/galtproject/geesome-libs.git

or yarn:

yarn add git://github.com/galtproject/geesome-libs.git
  1. Checkout GeeSome API documentation

  2. Get apiKey from node by api and login pass authorization:

const { GeesomeClient } = require('geesome-libs/src/GeesomeClient');

const geesomeClient = new GeesomeClient({
    server: 'https://your-site.com/api', // or 'http://localhost:2052', it can be set by default in geesome node frontend
    // apiKey: '4J1VYKW-ZP34Y0W-PREH1Q2-DYN9Q8E' // if you paste your apiKey here, so no need to authorization by loginPassword function
});

geesomeClient.init().then(async () => {
    await geesomeClient.loginPassword("username", "password");
    console.log('Congrats! You successfully authorized, your session api key:', geesomeClient.apiKey);
});

Or you can generate apiKey from UI in User Profile section by "Add api key" button. More safer to use apiKey instead of login/password, because you can always disable it and create another if there is a leak.

  1. Init GeeSome client and save image to your IPFS node
geesomeClient.init().then(async () => {
    const contentObj = await geesomeClient.saveDataByUrl('https://picsum.photos/500/300.jpg');
    console.log('content ipfs', contentObj.storageId);
    console.log('content manifest ipld', contentObj.manifestStorageId);
});
  1. Create group and publish post via API
geesomeClient.init().then(async () => {
    const avatarPhoto = await geesomeClient.saveDataByUrl('https://picsum.photos/500/300.jpg');
    
    const group = await geesomeClient.createGroup(testUser.id, { name: 'test', title: 'Test', avatarImageId: avatarPhoto.id });

    const groupIpns = group.manifestStaticStorageId;
    console.log('group manifest ipld', group.manifestStorageId);
    console.log('group manifest ipns that points to ipld', groupIpns);
    
    const postContent1 = await geesomeClient.saveContentData('My first post');
    const postContent2 = await geesomeClient.saveDataByUrl('https://picsum.photos/1000/500.jpg');
    
    await geesomeClient.createPost([postContent1.id, postContent2.id], { groupId: group.id, status: 'published' });
    
    // get published group from IPFS with posts
    
    // resolve IPNS first
    const updatedGroupIpld = await geesomeClient.resolveIpns(groupIpns);
    console.log('new group manifest ipld with first post', updatedGroupIpld);
    
    // get JSON content of group by IPLD
    const updatedGroupManifest = await geesomeClient.getObject(updatedGroupIpld);
    console.log('fetched group manifest', updatedGroupManifest);
    // or you can simply use geesomeClient.getGroup(groupIpns) for auto-resolve IPNS, get manifest with avatar and cover contents included
    
    // get posts one by one from group's posts tree
    geesomeClient.getGroupPostsAsync(
      updatedGroupIpld, 
      {limit: 10, offset: 0, orderDir: 'desc'}, 
      function onItemCallback(fetchedPost) {
        console.log('fetchedPost', fetchedPost);
        console.log('fetchedPost contents array', fetchedPost.contents);
      }, 
      function onFinishCallback(postList) {
        console.log('postList', postList);
      }
    );
});
  1. Create and publish IPFS site directory with content to IPNS
geesomeClient.init().then(async () => {
    await geesomeClient.saveDataByUrl('https://picsum.photos/500/300.jpg', {path: '/my-site/image.jpg'});
    
    await geesomeClient.saveContentData('<h1>Hello world!</h1> <img src="./image.jpg"/>', {path: '/my-site/index.html'});
    
    const mySiteFolder = await geesomeClient.getFileCatalogItemByPath('/my-site/', 'folder');
    
    const {storageId, staticId} = await geesomeClient.publishFolder(mySiteFolder.id);
    
    console.log(`check out by IPFS hash: ${geesomeClient.server}/ipfs/${storageId}/`); // for example: https://your-site.com:7722/ipfs/QmbDxAcbnSc5bgX77MgqqZ9bPVcczv5McZAYrWXoRxExi8/

    console.log(`check out by IPNS hash: ${geesomeClient.server}/ipns/${staticId}/`); // for example: https://your-site.com:7722/ipns/QmcqRcmu7p3UHkMPz8XJ886KPWbzxgpc9uNXy9GUDfUD87/
    
    // resolve IPNS by api:
    const resolvedStorageId = await geesomeClient.resolveIpns(staticId);
    
    console.log(storageId === resolvedStorageId); // true
});

Current state and features:

  • Browser-first encrypted direct messages and attachments with client-held device keys, opaque node storage, authenticated delayed inter-node delivery, and signed history repair; group key rotation and multi-node browser testing remain
  • Public channels and posts
  • Streamable media api(video and audio)
  • Basic file manager
  • User profile
  • Api keys for access to all node features
  • Api keys managment in UI
  • Separated content and folders list and access by users
  • Users upload limits
  • IPNS caching for fast resolving
  • IPFS and IPNS directories for HTML sites and more
  • Ethereum authentication by signature
  • Import telegram channel's posts
  • Generate static sites from groups with posts and upload to IPFS
  • Invite system for new users
  • Auto-backup social networks channels(Telegram)

TODO:

  • Complete the remaining operator-run ActivityPub/Bluesky release gates: credentialed native Bluesky writes, public staging-node inbox/outbox exchange, and external signed-ownership proof compatibility.
  • Complete browser-first secure chat with a maintained group membership/key-rotation implementation, retention quotas, and real multi-node browser tests. Private keys and plaintext remain on user devices; nodes persist and route only opaque encrypted envelopes and delivery metadata.
  • Finish API route ownership and public-route abuse coverage before expanding federation and secure-chat surfaces.
  • Complete static-site settings validation and generated frontend delivery while preserving the stabilized renderer.
  • Attribute reported content-serving CPU saturation across GeeSome, Kubo, PostgreSQL, nginx, media conversion, and storage I/O before changing runtime behavior.
  • Test Node 24 as the next runtime target and continue bounded cleanup of legacy moderate dependency chains.
  • Fix remaining sticker/media preview issues and design safe resumable uploads without allowing active SVG content into browser render paths.
  • Expand group views toward thread/feed use cases while preserving current APIs and large-group cursor pagination.
  • Improve resumable, idempotent Telegram and Twitter-compatible backup/import workflows.
  • Tune the completed database scalability, pinning, and storage analyzer foundations from restored-production and live Kubo/provider evidence.
  • Keep local browser IPNS signing, PubSub backup, Matrix/Filecoin/search integrations, and mobile/browser apps as separate epics.

See docs/todo.md for active deterministic implementation sections and docs/implemented.md for delivered foundations and verification history.

GeeSome Services

You can develop your own GeeSome service in any programming language for extend GeeSome node functional by communication by API with api keys. Service can communicate with GeeSome node by http requests and PubSub events(in future) for uploading content, managing users and groups.

Existing services:

  • GeeSome ETH Manager: Ethereum listener library for managing GeeSome node by Smart Contracts events: register users, set storage limits.

Minimal requirements

  • System: Ubuntu 22.04 (Jammy) or newer
  • RAM for running the node: 2 GB minimum with swap, 4 GB recommended. The app process itself is comparatively small: measured startup peaks around 350 MB and settles around 300 MB, while the light-use stack (node + IPFS + Postgres) stayed under about 1.75 GB.
  • RAM for Docker install/upgrade builds: 4 GB RAM with 8 GB swap recommended. Building the Docker image can rebuild native packages, bundle the frontend, and minify large JavaScript chunks; these phases can temporarily use more than 1 GB in one Node process while IPFS/Postgres are still running. Initialize swap with bash/ubuntu-init-swapfile.sh.
  • CPU: 2 cores recommended for Docker builds and media processing. A single-core server can run the node, but frontend builds, native dependency rebuilds, and video transcoding will be slow.
  • Disk: 10 GB free minimum for Docker image/build cache, 20 GB+ recommended, plus space for your files, IPFS repo, and Postgres data. Existing Docker images and warm build caches can exceed the old 3-4 GB estimate.
  • Concurrent video transcoding or large imports need extra headroom. You can profile your own load with the memory tooling in DEBUG.md.

Dependencies

  • GO IPFS or IPFS JS
  • Node 22.x
  • Sqlite
  • ffmpeg
  • Cerbot(Letsencrypt)

Publishing Docker images for a release

See Docker image publication and deployment for registry login, SHA-tag publication, release aliases, local release checks, platform support and rollback. The release agent builds and publishes from the local machine after the final merge; GitHub Actions does not publish Docker images.

Local install and run

sudo chmod +x bash/*.sh && sudo bash/ubuntu-install-docker.sh
npm run docker

Open UI page by url: http://localhost:2042

Api available by http://localhost:2052 endpoint.

Tests

For quick module checks, run the targeted Mocha command that matches the changed area, for example:

node --import tsx --experimental-global-customevent ./node_modules/.bin/mocha test/pinUnit.test.ts

For the full suite, use the Docker-backed flow as the primary verification path:

npm run test:docker

The default Docker test path is optimized for warm reruns while implementing. It reuses Docker dependency layers and keeps PostgreSQL/IPFS data between runs, while still rebuilding the source snapshot and starting the GeeSome test process fresh. Use it after ordinary source changes.

Use a cold reset when service state, generated data, package files, or Docker setup changed:

npm run test:docker:cold

When a Docker image has already been built and you need to rerun the exact same source snapshot, the fastest loop can skip the build check:

npm run test:docker:no-build

The Docker test flow builds a Node 22 test image with ffmpeg, starts PostgreSQL and two isolated Kubo daemons through test/docker-compose.yml, waits for those services, generates deterministic media/archive fixtures under test/resources, then runs the test suite inside the test container. The second Kubo daemon gives the independent chat-node harness a distinct storage peer. Kubo RPC storage services are treated as externally owned and are not stopped during app teardown. Set STORAGE_STOP_REMOTE_NODE=1 only when the GeeSome process intentionally owns that Kubo daemon and should stop it with the app.

Links

Articles

  • How to make the internet great again
  • Signing and encrypt messages by IPNS keys (Soon...)
  • How to add site to IPFS with GeeSome node (Soon...)
  • Use GeeSome as IPFS file storage in your decentralized project (Soon...)
  • IPNS updates problem and how we solved it (Soon...)
  • Are we ready for true decentralized messages and content? (Soon...)
  • We need backups for our Social Networks! (Soon...)

Do you like the project? ✨

Put a star and fork it. Join Us On Telegram. Thank you!

About

🦈 Your self-hosted decentralized Messenger, Social network, Media file storage on top of IPFS! Freely communicate in encrypted chat groups, share images, video, text or any data without a risk of censorship or blocking.

Topics

Resources

Stars

132 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages