There’s a bunch of ways to approach this.
One is to use a script to connect to the 2 servers, traverse a Project -> Dataset -> Images and Annotations on the private server and duplicate the whole graph onto the public server.
For example, for setting up training data, we use https://github.com/ome/training-scripts/blob/master/maintenance/scripts/idr_copy_plate.py to copy a plate from the IDR server onto a training server. This creates new images with the same pixel data by copying the data via a numpy array (and only takes the first time-point of timelapse images). You could also do this by downloading the images and re-importing if you want the same original files.
For annotations you could do the same: This script traverses P>D>I on the origin server (IDR) and copies Map Annotations to the corresponding images on the target server (matching images by name). https://github.com/ome/training-scripts/blob/master/maintenance/scripts/idr_get_map_annotations.py
I seem to remember one user experimenting with a server-side OMERO.script on the ‘private’ server which any user could run to export their data to another server, but I don’t know where this got to.
A different approach might be to export with https://github.com/ome/omero-downloader and re-import. The downloader includes some annotations in the exported OME-XML which should be re-created in the public server when re-imported, but I haven’t tried this.
If you want to try a script, we’d be happy to help as it’s certainly something that has been asked about before.