{"id":13770261,"url":"https://github.com/svenvc/pharo-server-tools","last_synced_at":"2025-10-23T02:31:13.032Z","repository":{"id":146208704,"uuid":"41351864","full_name":"svenvc/pharo-server-tools","owner":"svenvc","description":"Tools to deploy and manage headless Pharo servers from the command line","archived":false,"fork":false,"pushed_at":"2023-07-05T13:12:31.000Z","size":42,"stargazers_count":26,"open_issues_count":1,"forks_count":5,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-09-26T21:40:22.187Z","etag":null,"topics":["deployment","pharo","server","smalltalk"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/svenvc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-08-25T08:11:32.000Z","updated_at":"2024-08-19T15:29:10.000Z","dependencies_parsed_at":"2024-01-07T22:21:38.857Z","dependency_job_id":null,"html_url":"https://github.com/svenvc/pharo-server-tools","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenvc%2Fpharo-server-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenvc%2Fpharo-server-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenvc%2Fpharo-server-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenvc%2Fpharo-server-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/svenvc","download_url":"https://codeload.github.com/svenvc/pharo-server-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219868427,"owners_count":16555761,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deployment","pharo","server","smalltalk"],"created_at":"2024-08-03T17:00:35.673Z","updated_at":"2025-10-23T02:31:12.739Z","avatar_url":"https://github.com/svenvc.png","language":"Shell","funding_links":[],"categories":["Projects management"],"sub_categories":[],"readme":"# Pharo Server Tools\n\nTools to deploy and manage headless Pharo servers from the command line.\n\n\n## Goal\n\nTo deploy and manage a Pharo based server application on a Linux system.\nMore specifically, Pharo 4 on Ubuntu 14.04 LTS server.\n\nThe goal is to integrate well within the standard Linux world,\n\n- create an entry in `/etc/init.d` or `/etc/systemd/system/` for automatic start/stop/restart\n- create an entry in `/etc/monit/conf.d` for monitoring with automatic restarts whenever the check fails\n- setup logging to daily files\n- setup secure REPL access to the running application\n\nThis document describes the basic manual installation procedure.\nThere is also an interactive scaffold script that automates most work.\n\n\n## Installation\n\nNote that we assume that you operate your machine as a normal user.\n\n````bash\necho $USER\n````\n\nCheck out the project `pharo-server-tools` from github.\nYou will need to install git first\n\n````bash\nsudo apt-get install git-core \ngit clone https://github.com/svenvc/pharo-server-tools.git\n````\n\nThe following directory structure is used\n\n````bash\n~/pharo\n~/pharo/bin\n~/pharo/bin/pharo-vm\n~/pharo/build\n````\n\nThe script `install-pharo.sh` will download a Pharo 4 image + VM\nand move things around to create the directory structure.\nThis has to be done only once. You will need to install unzip.\n\n````bash\nsudo apt-get install unzip\n~/pharo-server-tools/install-pharo.sh\n````\n\nYou can use both a 32 or 64 bit Ubuntu distribution.\nHowever, since the Pharo VM is still a 32 bit application, \nyou will need to install some extra libraries in that case.\n\nThe standard instructions are\n\n````bash\nsudo dpkg --add-architecture i386\nsudo apt-get update\nsudo apt-get install libc6:i386\nsudo apt-get install libssl1.0.0:i386\nsudo apt-get install libfreetype6:i386\n````\n\nYou can use the script `ubuntu-32bit-support-on-64bit.sh` for this.\n\n\n## Server Application\n\nIt is assumed your whole application is packaged using \none single Metacello configuration that loads all dependencies.\n\nNote that if you want to use the REPL and HTTP monitoring features described here, you need to include NeoConsole as one of your dependencies.\n\n````\nproject: 'NeoConsole' with: [\n  spec \n    className: 'ConfigurationOfNeoConsole';\n    repository: 'http://mc.stfx.eu/Neo' ];\n````\n\nFurthermore it is assumed that you have a script that actually\nstarts up your application. This could be as simple as\n`MyApp start` but will probably be a bit more involved.\n\nEach server application will eventually be deployed and run\nfrom its own directory under `~/pharo`. From the operational\nstandpoint this is the only relevant place.\n\nNext we describe the different steps needed\nto set everything up manually.\nThere is also an interactive script to automate all these steps.\n\n````bash\n./pharo-server-tools/scaffold.sh\n````\n\nHere is an example usage, installing a Pharo HTTP Server, with NeoConsole as sole dependency.\n\n````bash\n$ ./scaffold.sh \nThis script will setup a new Pharo service under /home/t3/pharo\nService name: pharo-http-server\nImage name (empty for service name): \nUser (empty for current user): \nDescription: Pharo HTTP Server\nMetacello repository: http://mc.stfx.eu/Neo\nMetacello name: ConfigurationOfNeoConsole\nMetacello user (empty for none): \nMetacello password (empty for none): \nMetacello version (empty for stable): \nMetacello group (empty for default): \nTelnet port (empty for 42001): \nMetrics port (empty for 42002): \nCreating custom build script\nThis script will build a pharo-http-server image\n'Installing ConfigurationOfNeoConsole stable'\n\nLoading 8 of ConfigurationOfNeoConsole...\nFetched -\u003e Neo-Console-Core-SvenVanCaekenberghe.15 --- http://mc.stfx.eu/Neo --- http://mc.stfx.eu/Neo\nLoaded -\u003e Neo-Console-Core-SvenVanCaekenberghe.15 --- http://mc.stfx.eu/Neo --- cache\n...finished 8\nCreating custom run/startup script\nCreating custom REPL script\nCreating custom init.d script\nCreating custom systemd.service script\nCreating custom monit service check\nDone\nTo install the init.d script do\nsudo cp /home/t3/pharo/pharo-http-server/init.d.script /etc/init.d/pharo-http-server\nsudo update-rc.d pharo-http-server defaults\nTo install the systemd.service script do\nsudo cp /home/t3/pharo/pharo-http-server/systemd.service.script /etc/systemd/system/pharo-http-server.service\nsudo systemctl daemon-reload\nsudo systemctl enable pharo-http-server\nTo install the monit service check do\nsudo cp /home/t3/pharo/pharo-http-server/monit-service-check /etc/monit/conf.d/pharo-http-server\n````\n\n\n## Building\n\nPharo uses an image to hold all the objects and code needed to run\nan application. You need to build your custom image by loading\nyour code into the standard image. This build from source step is\nexecuted in the `~/pharo/build` directory.\n\nBuilding will be done incrementally in a scratch image called\n`build.image`. This is created once or whenever you want to \ncompletely start over. In the build directory do\n\n````bash\n../bin/pharo Pharo.image save build\n````\n\nNow edit the build.sh script to refer to load your configuration.\nThe default just loads NeoConsole for the REPL tool, a dependency\nyou should add to your own projects. For the demo/tutorial this\nwill be enough.\n\n````bash\n./build.sh\n````\n\nAfter a successful build, copy the image again. Our demo/tutorial\napplication will be called `pharo-http-server`.\n\n````bash\n../bin/pharo build.image save pharo-http-server\n````\n\nWhen you update your code, you execute the last 2 steps again.\n\n\n## Deploying\n\n### Preparing the deploy directory\n\nStart by creating your deploy directory\n\n````bash\nmkdir ~/pharo/pharo-http-server\n````\n\nNow move over the customised image and changes files that were\ncreated in the build step\n\n````bash\nmv ~/pharo/build/pharo-http-server.* ~/pharo/pharo-http-server\n````\n\nTo control our application process itself, to start it in the background,\nto figure out whether it is running and its process id, to stop it,\nwe use a helper script called `pharo-ctl.sh`. Copy it \n\n````bash\ncp ~/pharo-server-tools/pharo-ctl.sh ~/pharo/pharo-http-server\n````\n\nNext we need a run or startup script. The template is good for the\ndemo/tutorial, you will probably have to customise it. Copy it\n\n````bash\ncp ~/pharo-server-tools/run.st.template ~/pharo/pharo-http-server/run-pharo-http-server.st\n````\n\nHere is the script’s contents:\n\n````smalltalk\n(NeoConsoleTranscript onFileNamed: 'server-{1}.log') install.\n\nTranscript\n  cr;\n  show: 'Starting '; show: (NeoConsoleTelnetServer startOn: 42001); cr;\n  show: 'Starting '; show: (NeoConsoleMetricDelegate startOn: 42002); cr;\n  flush.\n\n(ZnServer defaultOn: 8080)\n  logToTranscript;\n  logLevel: 2;\n  start.\n````\n\nThe first expression installs a non-interactive transcript that redirects\nall Transcript output to files which are organised by day.\n\nNext, the tools from the NeoConsole project are used to start 2 helper services.\nThe first is a locally bound Telnet server that allows for REPL access \nto a running image which is very useful for debugging and monitoring purposes.\nThe second is a locally bound HTTP server that gives access to a number\nof metrics, named read-only properties, among which is `system.status`.\n\nFinally we start our application, an HTTP server on port 8080, with logging.\n\nWe now have everything set up to manually run our application server.\nThe `pharo-ctl` script always takes 3 arguments, the name of the \nstartup script, the desired operation and the name of the image.\nExecute it without arguments for help\n\n````bash\n./pharo-ctl.sh \nExecuting ./pharo-ctl.sh\nWorking directory /home/sven/pharo/pharo-http-server\nUsage: ./pharo-ctl.sh \u003cscript\u003e \u003ccommand\u003e \u003cimage\u003e\n    manage a Pharo server\nNaming\n    script       is used as unique identifier\n    script.st    must exist and is the Pharo startup script  \n    script.pid   will be used to hold the process id\n    image.image  is the Pharo image that will be started\nCommands:\n    start    start the server in background\n    stop     stop the server\n    restart  restart the server\n    run      run the server in foreground\n    pid      print the process id \n````\n\nNote that the extensions `.st` and `.image` are added automatically.\n\nHere is how to start our application\n\n    ./pharo-ctl.sh run-pharo-http-server start pharo-http-server\n\nNote that the image could be started multiple times, like when running N\ninstances for load balancing, but the startup/run script should be unique,\nlike `run.0.st`, `run.1.st` and so on. The combination image/script should\nbe unique on your machine.\n\nTo figure out whether it is running and get its process id (PID)\n\n````bash\n./pharo-ctl.sh run-pharo-http-server pid pharo-http-server\n````\n\nTo stop the background process\n\n````bash\n./pharo-ctl.sh run-pharo-http-server stop pharo-http-server\n````\n\nYou can invoke this last command multiple times if you somehow managed \nto start multiple copies.\n\n\n### Integrating with Linux Init Scripts\n\nYou want your application server to be under control of Linux,\nso that it will start automatically whenever your machine (re)starts.\nSystem administrators need this so called service entry to learn \nabout your application. We will reuse this feature ourselves later on as well.\n\n#### init.d\n\nTo do this you have to create a script inside `/etc/init.d`.\nCopy the template and update the System V style RC init subsystem:\n\n````bash\nsudo cp ~/pharo-server-tools/init.d.template /etc/init.d/pharo-http-server\nsudo update-rc.d pharo-http-server defaults\n````\n\nAgain, the script is more or less ready for our demo/tutorial.\nCheck the variables at the top, you need to change the `user` in \nthe `PHDIR=` and `SU=` lines to the actual user you are using.\n\nIf everything is well, Linux can now control your application.\n\n````bash\nsudo service pharo-http-server\nsudo service pharo-http-server start\nsudo service pharo-http-server stop\n````\n\n#### systemd\n\nAlternatively, you can use the newer systemd approach.\nTo do this you have to create a script inside `/etc/systemd/system`.\nCopy the template, reload the daemon and enable the service.\n\n````bash\nsudo cp ~/pharo-server-tools/systemd.service.template /etc/systemd/system/pharo-http-server.service\nsudo systemctl daemon-reload\nsudo systemctl enable pharo-http-server\n````\n\nMake sure to change the user. Now you can manipulate the service in a standard way.\n\n````bash\nsudo systemctl stop pharo-http-server\nsudo systemctl start pharo-http-server\nsudo systemctl status pharo-http-server\n````\n\n\n### Integrating with monitoring\n\nYour application server might crash or become otherwise unresponsive.\nYou want automatic monitoring of some external feature of your\napplication server with the option to restart it should the service check fail.\n\nIn our startup script we started a special, locally bound HTTP server just\nfor this purpose, running on port 42002. The URI `/metrics/system.status` gives\na simple service status indication.\n\n````bash\ncurl http://localhost:42002/metrics/system.status\n````\n\nWhich returns a single line of text, like\n\n    Status OK - Clock 2015-08-25T14:21:08.641321+02:00 - Allocated 51,123,436 bytes - 14.63 % free.\n\nWe chose to use monit for this purpose.\n\n````bash\nsudo apt-get install monit\n````\n\nNow copy over the monit-service template corresponding to your choice of startup (init.d or systemd)\n\n_Using init.d_\n````bash\nsudo cp ~/pharo-server-tools/monit-service-init.d.template /etc/monit/conf.d/pharo-http-server\n````\n\n_Using systemd_\n````bash\nsudo cp ~/pharo-server-tools/monit-service-systemd.template /etc/monit/conf.d/pharo-http-server\n````\n\nEdit the file by replace `user` with your username and restart monit, \nafter validating validating the syntax.\n\n````bash\nsudo service monit syntax\nsudo service monit restart\n````\n\nThe contents of the service check is pretty simple:\n\n````bash\ncheck process pharo-http-server\n    with pidfile \"/home/user/pharo/pharo-http-server/run-pharo-http-server.pid\"\n    start program = \"/etc/init.d/pharo-http-server start\"\n    stop program = \"/etc/init.d/pharo-http-server stop\"\n    if failed url http://localhost:42002/metrics/system.status\n       timeout 10 seconds retry 3\n       then restart \n````\n\nIt says to check the specified URL and restart if there is no successful response to it,\nretrying 3 times with a timeout of 10 seconds each time. \n\nNote how we reuse the init script and the PID file.\nWhen using systemd, you will need to modify the start and stop programs accordingly.\n\nConsult monit’s documentation for more options, like email notifications.\n\n\n### REPL telnet access to a running image\n\nAlthough log files are a standard way to learn about a running background process,\nit is a very primitive interface. You either log too little or too much. \nOften you would just love to have a look inside your running application.\n\nWith NeoConsole’s REPL (read-eval-print-loop) telenet access you can do just that.\nIn our startup script we started a special, locally bound Telnet server\non port 42001.\n\n````bash\ntelnet localhost 42001\n\n./repl.sh\n````\n\nYou can use telnet directly or use the repl.sh script.\nHere is a transcript of a session with this tool.\n\n````bash\nTrying 127.0.0.1...\nConnected to localhost.\nEscape character is '^]'.\nNeo Console Pharo4.0 of 18 March 2013 update 40618\n\u003e help\nhelp \u003ccommand\u003e\nknown commands are:\n  describe\n  eval DEFAULT\n  get\n  help\n  history\n  quit\n\u003e get\nknown metrics:\n  system.status - Simple system status\n  memory.total - Total allocated memory\n  memory.free - Free memory\n  system.date - Current date\n  system.time - Current time\n  system.timestamp - Current timestamp\n  process.count - Current process count\n  process.list - Current list of processes\n  system.version - Image version info\n  system.mcversions - Monticello packages version info\n\u003e get system.status\n  Status OK - Clock 2015-08-25T14:31:07.769294+02:00 - Allocated 55,551,212 bytes - 11.44 % free.\n\u003e 123 factorial\n\n12146304367025329675766243241881295855454217088483382315328918161829235892362167668831156960612640202170735835221294047782591091570411651472186029519906261646730733907419814952960000000000000000000000000000\n\u003e 0@0 extent: 10@20\n\n(0@0) corner: (10@20)\n\u003e =\nself: (0@0) corner: (10@20)\nclass: Rectangle\norigin: (0@0)\ncorner: (10@20)\n\u003e quit\nBye!\nConnection closed by foreign host.\n````\n\nThere is an executable script called repl.sh that helps you remember how to connect\nto the telnet REPL service.\n\n\n## Troubleshooting\n\nCarefully read the run/startup script, the init.d script and the service check script.\nPath names and port numbers should match.\nDouble check that the right processes run (`ps auxw | grep pharo`).\n\n\n## Resources\n\nThe following chapter from the 'Enterprise Pharo, a Web prespective' \ntreats the same subject: \n[Deploying a Pharo web application in production](https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/DeploymentWeb/DeployForProduction.html)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenvc%2Fpharo-server-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvenvc%2Fpharo-server-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenvc%2Fpharo-server-tools/lists"}