Introduction
The last few weeks I did some development to make JDownloader run on server and NAS systems which do not have any XServer installed. This HowTo will explain how you can get JDownloader running without Graphical User Interface.

Short Version (for pro users)

Copy an existing JDownloader2 installation from a desktop system to your server system or NAS. Be sure to setup My.JDownloader before copying the files.

Add GhostAWT to your JDownloader installation using the following commands (check "**External links are only visible to Support Staff** for the latest release)

1.1 Get Package
As a first step we need to build a JDownloader2 package for our system. Currently JDownloader2 is only available as special offline installer packages. The problem: This installer might not run on server systems without a UI and it’s only available for x86/x64 systems. http://jdownloader.org/download/offline
For me the offline installer worked on an Ubuntu 32bit Server installation, but it didn’t work on my Synology NAS. To keep this HowTo simple, I will describe another solution:

1.2 Configure Package
Start JDownloader on your desktop and let it update to the latest version. Since we won’t have a UI on our server system we should configure our JDownloader on our desktop. Open the settings and configure it the way you like. Here are some recommended settings for server systems:

User Interface

Enable Silent Mode

Bubble Notify

Show Bubbles if Never

Tray Icon

Uncheck Enabled

The most important thing is to setup your My.JDownloader settings. It will be the only way to control JDownloader.

1.3 Copy Package
Once your JDownloader is ready go into your JDownloader installation directory and copy all files to your server system. Do not copy the JRE directory, we won’t use the Java Runtime installed with JDownloader.

2. Run JDownloader using GhostAWT

Now we need to get JDownloader running on our environment. The problem is: If we start JDownloader normally, it will just crash because there’s no GUI. This is where GhostAWT comes in place. It’s a platform implementation of AWT and Java2D which makes Java believe there’s a UI available. If Java tries to create a window or do any graphical operations, GhostAWT will simply do nothing instead of crying no XServer is installed.

Let’s download GhostAWT and copy it into JDownloader. Head to "**External links are only visible to Support Staff** and copy the link of the latest Source code tar.gz. On our server system we download the file, extract it, and copy the files of the dist directory to our JDownloader installation:

Replace synology-marvell-armada-370 with the correct platform of your system. I recommend to create a new shell script with this startup command.
In the first release of GhostAWT x86 linux systems (linux32) and Synology Marvell Armada 370 ARM (synology-marvell-armada-370) are available. If GhostAWT does not support your platform you should try compiling it for your platform on your own or create a new issue on "**External links are only visible to Support Staff**

3. My.JDownloader Settings
After starting JDownloader you should able to log in into My.JDownloader and see the connected device there. Before downloading any files you should go to the settings tab and open the „Advanced Config“.

There enter „Default Download Folder“ into the search box and set adjust the path to match your desired download location. I copied my Windows installation to my Synology Diskstation, that’s why a Windows File System Path was set. Make it fit your needs.

Enter „Browser Command Line“ into into the search box and click reset there. I also had some Windows specific stuff there.

4. Fin
Everything is done and ready for downloading. Enjoy your server/NAS JDownloader. If you encounter any problems feel free to ask here.

--ID:13TS:1402570530342-12/06/14 12:55:30 - [org.appwork.txtresource.TranslationHandler(createTranslationResource)] -> Utils>JDownloader.log>Load Translation file:/usr/local/jd2/translations/org/appwork/utils/locale/AWUTranslation.fr.lng
--ID:13TS:1402570530342-12/06/14 12:55:30 - [org.appwork.txtresource.TranslationHandler(createTranslationResource)] -> Utils>JDownloader.log>Load Translation file:/usr/local/jd2/translations/org/appwork/utils/locale/AWUTranslation.en.lng
--ID:13TS:1402570530406-12/06/14 12:55:30 - [org.appwork.utils.swing.dialog.ExceptionDialog(<init>)] -> Utils>JDownloader.log>Dialog [null][null]
flag: 100000010000
title: Exception occured
msg:
An unexpected error occured.
JDownloader will try to fix this. If this happens again, please contact our support.
--ID:13TS:1402570530408-12/06/14 12:55:30 - [org.appwork.utils.swing.dialog.AbstractDialog(displayDialog)] -> Utils>JDownloader.log>Display Dialog: dialog_Exception_occured_An_unexpected_error_occured___JDownloader_will_try_to_fix_this__If_this_hap pens_again__please_contact_our_support_
--ID:13TS:1402570531152-12/06/14 12:55:31 - [org.appwork.utils.swing.EDTHelper.run(EDTHelper.java:90)] -> Utils>JDownloader.log>SEVERE Exception occurred
java.lang.NullPointerException
at java.awt.Font.getFont2D(Font.java:498)
at java.awt.Font.access$000(Font.java:224)
at java.awt.Font$FontAccessImpl.getFont2D(Font.java:228)
at sun.font.FontUtilities.getFont2D(FontUtilities.java:180)
at sun.font.FontDesignMetrics.initMatrixAndMetrics(FontDesignMetrics.java:357)
at sun.font.FontDesignMetrics.<init>(FontDesignMetrics.java:350)
at sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:302)
at sun.swing.SwingUtilities2.getFontMetrics(SwingUtilities2.java:1003)
at javax.swing.JComponent.getFontMetrics(JComponent.java:1615)
at javax.swing.plaf.basic.BasicGraphicsUtils.getPreferredButtonSize(BasicGraphicsUtils.java:276)
at javax.swing.plaf.basic.BasicButtonUI.getPreferredSize(BasicButtonUI.java:376)
at javax.swing.plaf.basic.BasicButtonUI.getMaximumSize(BasicButtonUI.java:380)
at javax.swing.JComponent.getMaximumSize(JComponent.java:1693)
at net.miginfocom.swing.SwingComponentWrapper.getLayoutHashCode(Unknown Source)
at net.miginfocom.swing.MigLayout.checkCache(Unknown Source)
at net.miginfocom.swing.MigLayout.getSizeImpl(Unknown Source)
at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source)
at java.awt.Container.preferredSize(Container.java:1788)
at java.awt.Container.getPreferredSize(Container.java:1773)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1653)
at net.miginfocom.swing.SwingComponentWrapper.getLayoutHashCode(Unknown Source)
at net.miginfocom.swing.MigLayout.checkCache(Unknown Source)
at net.miginfocom.swing.MigLayout.getSizeImpl(Unknown Source)
at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source)
at java.awt.Container.preferredSize(Container.java:1788)
at java.awt.Container.getPreferredSize(Container.java:1773)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1653)
at net.miginfocom.swing.SwingComponentWrapper.getLayoutHashCode(Unknown Source)
at net.miginfocom.swing.MigLayout.checkCache(Unknown Source)
at net.miginfocom.swing.MigLayout.getSizeImpl(Unknown Source)
at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source)
at java.awt.Container.preferredSize(Container.java:1788)
at java.awt.Container.getPreferredSize(Container.java:1773)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1653)
at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:917)
at java.awt.Container.preferredSize(Container.java:1788)
at java.awt.Container.getPreferredSize(Container.java:1773)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1653)
at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:719)
at java.awt.Container.preferredSize(Container.java:1788)
at java.awt.Container.getPreferredSize(Container.java:1773)
at org.appwork.utils.swing.dialog.InternDialog.getRawPreferredSize(InternDialog.java:116)
at org.appwork.utils.swing.dialog.AbstractDialog.getRawPreferredSize(AbstractDialog.java:1086)
at org.appwork.utils.swing.dialog.AbstractDialog.getPreferredSize(AbstractDialog.java:1050)
at org.appwork.utils.swing.dialog.InternDialog.getPreferredSize(InternDialog.java:110)
at java.awt.Window.pack(Window.java:809)
at org.appwork.utils.swing.dialog.AbstractDialog.pack(AbstractDialog.java:1335)
at org.appwork.utils.swing.dialog.AbstractDialog._init(AbstractDialog.java:467)
at org.appwork.utils.swing.dialog.AbstractDialog.displayDialog(AbstractDialog.java:712)
at org.appwork.utils.swing.dialog.Dialog.showDialogRawInEDT(Dialog.java:518)
at org.appwork.utils.swing.dialog.Dialog.showDialogRaw(Dialog.java:509)
at org.appwork.utils.swing.dialog.Dialog.showDialog(Dialog.java:497)
at org.appwork.utils.swing.dialog.Dialog.showExceptionDialog(Dialog.java:625)
at jd.SecondLevelLaunch$12.edtRun(SecondLevelLaunch.java:936)
at jd.SecondLevelLaunch$12.edtRun(SecondLevelLaunch.java:902)
at org.appwork.utils.swing.EDTHelper.run(EDTHelper.java:87)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)