Editor not displaying chapter content

I’m moving this problem to a new topic as the other one was getting a bit convoluted.

I can log in, create a book, the editor opens, I put in text for a title and style it, but the left side still says “Unknown Chapter”, and if I click out and come back the contents are gone. No errors that I can see anywhere in any of the docker containers or browser javascript console.

I uploaded a .docx file, it seems it was processed OK by xsweet, it added a new chapter with the title of the file (that is good!), but when I click on the chapter I see the same contents I already had in the editor, and clicking between that and the previous chapter just refreshes the same content.

If I click to add a new chapter I get a new chapter line with the editor that is still showing the same content I had before. But if you click in and out of them enough the editor just displays a blank page no matter what chapter you click on.

However, if you do a preview it will at least generate the content of the uploaded file chapter, but the content doesn’t display in the editor.

Hopefully this can help further diagnose what might be going wrong when trying to use the production containers. I’m a bit confused about the DB container and the pgvector stuff, I don’t know if there is a published “ketty DB” container but I didn’t see one, or if there is a published PostgreSQL image with pgvector already in it.

Here is my docker-compose.yml file:

version: "3"

networks:
  ketty-network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.31.255.0/24
  ssl-network:
    name: ssl-network
    external: true

services:
  client:
    restart: unless-stopped
    image: cokoapps/ketty-client:latest
    expose:
      - 8080
    environment:
      - SERVER_IDENTIFIER=scm_client_001
      - NODE_ENV=production
      - CLIENT_PORT=8080
      - CLIENT_FAST_REFRESH=1
      - CLIENT_PAGE_TITLE=Ketty System
      - CLIENT_LANGUAGE="en-US"
      - CLIENT_FEATURE_UPLOAD_DOCX_FILES=true
      - CLIENT_FEATURE_BOOK_STRUCTURE=false
      - SERVER_URL=https://ketty.mydomain.com/server/
      - WEBSOCKET_SERVER_URL=wss://ketty.mydomain.com/socket/
      - CLIENT_FAVICON_PATH=../static/ketida.ico
    tty: true
    networks:
      - ssl-network
      - ketty-network

  server:
    restart: unless-stopped
    image: cokoapps/ketty-server:latest
    depends_on:
      - db
      - s3
      - createbucket
      - epubchecker
      - pagedjs
      - xsweet
    expose:
      - 3000
      - 3333
    environment:
      - SERVER_IDENTIFIER=scm_server_001
      - NODE_ENV=production
      - KETIDA_FLAVOUR=LULU  # also tried VANILLA
      - PUBSWEET_SECRET=dev_secret
      - SERVER_URL=https://ketty.mydomain.com/server/
      - WEBSOCKET_SERVER_URL=wss://ketty.mydomain.com/socket/
      - CLIENT_URL=https://ketty.mydomain.com
      - SERVER_SERVE_CLIENT=false
      - POSTGRES_HOST=db
      - POSTGRES_PORT=5432
      - POSTGRES_DB=ketida_dev
      - POSTGRES_USER=dev_user
      - POSTGRES_PASSWORD=4cabc3783d22afc9688b82022a825367
      - ADMIN_USERNAME=admin
      - ADMIN_PASSWORD=fruity%riff84#
      - ADMIN_GIVEN_NAME=Admin
      - ADMIN_SURNAME=Adminius
      - ADMIN_EMAIL=steve@simplycharlottemason.com
      - SERVER_PORT=3000
      - WS_SERVER_PORT=3333
      - WS_HEARTBEAT_INTERVAL=3000
      - FAIL_SAFE_UNLOCKING_INTERVAL=12000
      - MAILER_USER=scmit@simplycharlottemason.com
      - MAILER_PASSWORD=xsmtpsib-ce02cc86a2032bbae908a9e5b799e25aff213137a6c6963c97cb8aa30737741a-qYLNJkSVgnfmAaU9
      - MAILER_SENDER=scmit@simplycharlottemason.com
      - MAILER_HOSTNAME=smtp-relay.sendinblue.com
      - PASSWORD_RESET_PATH_TO_PAGE=/password-reset
      - S3_PROTOCOL=https
      - S3_HOST=kettys3.mydomain.com
      #- S3_PORT=443 # If this is defined it doesn't work
      - S3_BUCKET=uploads
      - S3_ACCESS_KEY_ID_USER=ketida
      - S3_SECRET_ACCESS_KEY_USER=f8a05191687f2a56e0f5ba904d088c40
      - SERVICE_EPUB_CHECKER_CLIENT_ID=e4c87d76-53ad-436e-9e1a-fe0ba69e08b3
      - SERVICE_EPUB_CHECKER_SECRET=ihSUTCeAOL3YerTQ
      - SERVICE_EPUB_CHECKER_URL=https://ketty.mydomain.com/epub
      - SERVICE_PAGEDJS_CLIENT_ID=68f4545e-b40b-4290-a783-c62592e4dfdd
      - SERVICE_PAGEDJS_SECRET=8zrqBlBKHmKN2efz
      - SERVICE_PAGEDJS_URL=https://ketty.mydomain.com/pjs
      - SERVICE_XSWEET_CLIENT_ID=e2e0c500-e135-4ac0-8866-36a29e9e6a69
      - SERVICE_XSWEET_SECRET=kBF3B3mOxNcVzxsw
      - SERVICE_XSWEET_URL=https://ketty.mydomain.com/xsw
      - FEATURE_UPLOAD_DOCX_FILES=true
      - FEATURE_BOOK_STRUCTURE=false
      - FEATURE_POD=true
      # - AI_ENABLED=true
      # - CHAT_GPT_KEY=${CHAT_GPT_KEY}
      - TEMP_DIRECTORY_CRON_JOB_SCHEDULE=0 * * * *
      - TEMP_DIRECTORY_CRON_JOB_OFFSET=-1800000
      - TEMP_DIRECTORY_CLEAN_UP=true
    volumes:
      - ./config/local.js:/home/node/server/config/local.js
    networks:
      - ssl-network
      - ketty-network

  epubchecker:
    depends_on:
      - db-epubchecker
    image: cokoapps/epubchecker:1.2.1
    expose:
      - 3001
    environment:
      - SERVER_IDENTIFIER=scm_epub_001
      - PUBSWEET_SECRET=epubchecker_dev_secret
      - POSTGRES_USER=epubchecker_user_dev
      - POSTGRES_PASSWORD=epubchecker_user_password
      - POSTGRES_HOST=db-epubchecker
      - POSTGRES_DB=epubchecker_dev
      - POSTGRES_PORT=5432
      - SERVER_PORT=3001
      - CLIENT_ID=e4c87d76-53ad-436e-9e1a-fe0ba69e08b3
      - CLIENT_SECRET=ihSUTCeAOL3YerTQ
    entrypoint:
      [
        "sh",
        "scripts/wait-for-it",
        "db-epubchecker:5432",
        "--",
        "sh",
        "scripts/setupProdServer.sh",
      ]
    command: ["node", "server/startServer.js"]
    networks:
      - ssl-network
      - ketty-network

  pagedjs:
    depends_on:
      - db-pagedjs
    image: cokoapps/pagedjs:1.6.10
    expose:
      - 3003
    environment:
      - SERVER_IDENTIFIER=scm_pjs_001
      - PUBSWEET_SECRET=pagedjs_dev_secret
      - POSTGRES_USER=pagedjs_user_dev
      - POSTGRES_PASSWORD=pagedjs_user_password
      - POSTGRES_HOST=db-pagedjs
      - POSTGRES_DB=pagedjs_dev
      - POSTGRES_PORT=5432
      - SERVER_PORT=3003
      - PUBLIC_URL=https://ketty.mydomain.com/pjs
      - CLIENT_ID=68f4545e-b40b-4290-a783-c62592e4dfdd
      - CLIENT_SECRET=8zrqBlBKHmKN2efz
    security_opt:
      - seccomp:unconfined
    entrypoint:
      [
        "dumb-init",
        "--",
        "sh",
        "scripts/wait-for-it",
        "db-pagedjs:5432",
        "--",
        "sh",
        "scripts/setupProdServer.sh",
      ]
    networks:
      - ssl-network
      - ketty-network

  xsweet:
    depends_on:
      - db-xsweet
    image: cokoapps/xsweet:2.3.3
    expose:
      - 3004
    environment:
      - SERVER_IDENTIFIER=scm_xsw_001
      - PUBSWEET_SECRET=xsweet_dev_secret
      - POSTGRES_USER=xsweet_user_dev
      - POSTGRES_PASSWORD=xsweet_user_password
      - POSTGRES_HOST=db-xsweet
      - POSTGRES_DB=xsweet_dev
      - POSTGRES_PORT=5432
      - SERVER_PORT=3004
      - CLIENT_ID=e2e0c500-e135-4ac0-8866-36a29e9e6a69
      - CLIENT_SECRET=kBF3B3mOxNcVzxsw
    entrypoint:
      [
        "sh",
        "scripts/wait-for-it",
        "db-xsweet:5432",
        "--",
        "sh",
        "scripts/setupProdServer.sh",
      ]
    command: ["node", "server/startServer.js"]
    networks:
      - ssl-network
      - ketty-network

  db:
    #image: postgres:14.4-alpine
    #the above image does not have vector type support
    #so I had to download the git repo and build it
    build:
      context: ./server
      dockerfile: Dockerfile-pgvector
    expose:
      - 5432
    environment:
      - SERVER_IDENTIFIER=scm_db_001
      - POSTGRES_DB=ketida_dev
      - POSTGRES_USER=dev_user
      - POSTGRES_PASSWORD=4cabc3783d22afc9688b82022a825367
    volumes:
      - ./db-data:/var/lib/postgresql/data
      - ./scripts/init-pgboss.sql:/docker-entrypoint-initdb.d/init-pgboss.sql
    networks:
      - ketty-network

  db-epubchecker:
    #image: postgres:14.4-alpine
    # May not be nessary to build, but I thought they would be consistent
    build:
      context: ./server
      dockerfile: Dockerfile-pgvector
    environment:
      - SERVER_IDENTIFIER=scm_dbepub_001
      - POSTGRES_USER=epubchecker_user_dev
      - POSTGRES_DB=epubchecker_dev
      - POSTGRES_PASSWORD=epubchecker_user_password
    volumes:
      - ./db-epubchecker-data:/var/lib/postgresql/data
      - ./scripts/init-pgboss.sql:/docker-entrypoint-initdb.d/init-pgboss.sql
    networks:
      - ketty-network

  db-pagedjs:
    #image: postgres:14.4-alpine
    # May not be nessary to build, but I thought they would be consistent
    build:
      context: ./server
      dockerfile: Dockerfile-pgvector
    environment:
      - SERVER_IDENTIFIER=scm_dbpjs_001
      - POSTGRES_USER=pagedjs_user_dev
      - POSTGRES_DB=pagedjs_dev
      - POSTGRES_PASSWORD=pagedjs_user_password
    volumes:
      - ./db-pagedjs-data:/var/lib/postgresql/data
      - ./scripts/init-pgboss.sql:/docker-entrypoint-initdb.d/init-pgboss.sql
    networks:
      - ketty-network

  db-xsweet:
    #image: postgres:14.4-alpine
    # May not be nessary to build, but I thought they would be consistent
    build:
      context: ./server
      dockerfile: Dockerfile-pgvector
    environment:
      - SERVER_IDENTIFIER=scm_dbxsw_001
      - POSTGRES_USER=xsweet_user_dev
      - POSTGRES_DB=xsweet_dev
      - POSTGRES_PASSWORD=xsweet_user_password
    volumes:
      - ./db-xsweet-data:/var/lib/postgresql/data
      - ./scripts/init-pgboss.sql:/docker-entrypoint-initdb.d/init-pgboss.sql
    networks:
      - ketty-network

  s3:
    # I had issues, so I moved to "latest" - it turned out it was a proxy
    # issue and having S3_PORT defined, but it seems to work with "latest"
    # image: minio/minio:RELEASE.2023-12-07T04-16-00Z
    image: minio/minio:latest
    expose:
      - 9000
      - 9001
    volumes:
      - minio_storage:/data
    environment:
      - SERVER_IDENTIFIER=scm_s3_001
      - MINIO_ROOT_USER=admin
      - MINIO_ROOT_PASSWORD=f8a05191687f2a56e0f5ba904d088c40
      - MINIO_BROWSER_REDIRECT_URL=https://kettys3.mydomain.com/console # YTY Add
      - MINIO_SERVER_URL=https://kettys3.mydomain.com # YTY Add
    command: server --console-address ":9001" /data
    networks:
      - ssl-network
      - ketty-network

  createbucket:
    image: minio/mc:RELEASE.2023-12-02T11-24-10Z
    depends_on:
      - s3
    entrypoint: >
      /bin/sh -c "
        sleep 10;
        /usr/bin/mc config host add ketida ${S3_PROTOCOL:-https}://${S3_HOST:-kettys3.mydomain.com} ${S3_ACCESS_KEY_ID_ADMIN:-admin} ${S3_SECRET_ACCESS_KEY_ADMIN:-f8a05191687f2a56e0f5ba904d088c40};
        /usr/bin/mc admin user add ketida/ ${S3_ACCESS_KEY_ID_USER:-ketida} ${S3_SECRET_ACCESS_KEY_USER:-f8a05191687f2a56e0f5ba904d088c40};
        /usr/bin/mc admin user enable ketida/ ${S3_ACCESS_KEY_ID_USER:-ketida};
        /usr/bin/mc mb ketida/${S3_BUCKET:-uploads};
        /usr/bin/mc admin policy attach ketida readwrite --user ${S3_ACCESS_KEY_ID_USER:-ketida};
        exit 0;
        "
        # When using PORT:
        # /usr/bin/mc config host add ketida ${S3_PROTOCOL:-https}://${S3_HOST:-kettys3.mydomain.com}:${S3_HOST:-443} ${S3_ACCESS_KEY_ID_ADMIN:-admin} ${S3_SECRET_ACCESS_KEY_ADMIN:-f8a05191687f2a56e0f5ba904d088c40};
        # :${S3_PORT:-443}
    networks:
      - ketty-network

volumes:
  minio_storage:

Extra proxy config for ketty.mydomain.com:

location / {
 proxy_pass $forward_scheme://$server:$port$request_uri;
 proxy_set_header Host $proxy_host;
}

location /server/ {
  proxy_pass http://server:3000/;
}

location /socket/ {
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
  # Uncomment the following line to set the Origin request to an empty string
  # proxy_set_header Origin '';
  chunked_transfer_encoding off;
  proxy_pass http://server:3333/;
}
location /pjs/ {
  proxy_pass http://pagedjs:3003/;
}
location /epub/ {
  proxy_pass http://epubchecker:3001/;
}

location /xsw/ {
  proxy_pass http://xsweet:3004/;
}

Extra proxy config for kettys3.mydomain.com:

# Allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;

location / {
     proxy_set_header Host $http_host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Forwarded-Proto $scheme;

     proxy_connect_timeout 300;
     # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
     proxy_http_version 1.1;
     proxy_set_header Connection "";
     chunked_transfer_encoding off;
     proxy_pass http://s3:9000/;
}

  location /console/ {
     rewrite ^/console/(.*) /$1 break;
     proxy_set_header Host $http_host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Forwarded-Proto $scheme;
     proxy_set_header X-NginX-Proxy true;
     # This is necessary to pass the correct IP to be hashed
     real_ip_header X-Real-IP;
     proxy_connect_timeout 300;
     # To support websockets in MinIO versions released after January 2023
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
     # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
     # Uncomment the following line to set the Origin request to an empty string
     # proxy_set_header Origin '';
     chunked_transfer_encoding off;
     proxy_pass http://s3:9001/;
}

I can’t edit the post (I can’t find a way) but all the keys/credentials/etc have been changed.

I found a Postgres14 Docker hub image with pgvector in it - ramsrib/pgvector:14 - and so can use that instead of the server/Dockerfile-pgvector for the database containers.

Hi @scmsteve

I would recommend following the steps outlined in our deployment documentation https://docs.ketty.community/docs/deploy/Deploy%20Ketty%20in%20production. I can’t say with certainty what is wrong with your setup, but in the instances we maintain we follow the procedure outlined in the docs. So setup up the microservices (with their respective dbs), an S3 bucket and the main database, and then in your docker compose you will declare only 2 services, client and server, with the right values in the env vars to connect to the other previously set up services. I’d like to debug your setup too, but currently we don’t have the resources for that.

Best,
Grigor

It doesn’t matter that the microservices are started in the same docker compose file, but I respect that you have no time to look at it. That just makes Ketty largely unusable for anyone to get online, as the docs you mention are so lacking in actual steps to take, no mention at all of required proxy directives to properly pass things through, and so forth. You really need to get whoever set up your demo/etc instances to document the process in a repeatable set of steps with complete sample configs.

1 Like

Hi Steve,

I came across Ketty (then Editoria) a few years ago. I initially attempted to set up a production server with it but was thwarted by the lack of documentation. I was about to attempt it again this week but I see the docs haven’t improved at all, and after reading your unanswered posts I’m wondering if I shouldn’t abandon ship completely.
Have you given up with it now or are you persevering? If you are, maybe we could collaborate on it to iron out the kinks.